React Native 팀이 NativeBase Picker와 마주치는 벽을 이미 여러 번 만났을 것입니다. 드롭다운이 렌더링되고 보기에 좋지만 iOS는 정상 작동하고, 안드로이드는 비즈니스 로직이 실행되지 않습니다. 오류도 없고 경고도 없지만, 픽커가 작동하는 것처럼 보입니다. onValueChange Martin Donadieu
그것은 경험한 개발자들을 놀라게 하는 NativeBase Picker의 그 틈새가 있다. 설정은 간단하고 스타일링은 관리가 가능하지만, 프로덕션의 신뢰성은 Android에 특화된 실패를 이해하는 데에 달려 있다. 대부분의 가이드는 그것을 생략하거나 언급하지 않는다.
목차
- NativeBase Picker와 함께 시작하기
- 상태를 바인딩하고 선택을 처리하기
- Android onValueChange 버그를 해결하기
- 스타일링 및 테마 설정
- 고급 시나리오 및 최적화 방법
- 결론
NativeBase 픩커와 함께 시작하기
픽커는 일반적으로 스프린트의 마지막에 추가하는 컴포넌트입니다. 국가 선택기, 상태 필드, 예약 타입, 배송 옵션. 플랫폼 동작이 UI에 유입될 때까지 작게 느껴집니다.
좋은 소식은 NativeBase 픩커가 NativeBase 픩커 화면에 표시하기 쉽습니다. iOS와 Android에서 원시 픽커를 렌더링하고, 더 이상 사용되지 않는 React Native Picker를 이전 NativeBase 설정에서 대체하기 위해 설계되었습니다. 따라서 많은 레거시 코드베이스가 여전히 그것에 의존합니다.

정상적인 React Native 설정에서 컴포넌트를 설치하세요.
NativeBase를 이미 사용 중인 프로젝트의 경우, 주된 작업은 올바른 원초체와 불필요한 wrapper 논리를 피하는 것입니다. 첫 번째 날부터 불필요한 wrapper 논리를 피하세요. 가장 단순한 표시 가능한 픽커부터 시작하세요.
모바일과 하이브리드 스택을 동시에 작업하는 경우, React code이 더 광범위한 환경인 React Native의 패키징 방식도 이해하는 것이 도움이 됩니다. React Native의 Capacitor을 사용하는 모바일 앱 워크플로입니다.code은 기본적으로 동일하지만 배포 예상치가 달라집니다.
기본적인 예제는 다음과 같습니다.
import React, { useState } from 'react';
import { Container, Content, Form, Item, Picker, Icon } from 'native-base';
export default function BasicPickerScreen() {
const [selectedValue, setSelectedValue] = useState('key0');
return (
<Container>
<Content padder>
<Form>
<Item picker>
<Picker
mode="dropdown"
iosIcon={<Icon name="arrow-down" />}
selectedValue={selectedValue}
onValueChange={(value) => setSelectedValue(value)}
>
<Picker.Item label="Choose one" value="key0" />
<Picker.Item label="JavaScript" value="js" />
<Picker.Item label="TypeScript" value="ts" />
<Picker.Item label="React Native" value="rn" />
</Picker>
</Item>
</Form>
</Content>
</Container>
);
}
추상화 없이 첫 번째 픽커를 렌더링하세요.
이 첫 번째 패스는 두 가지 질문만 대답해야 합니다.
- 정확하게 렌더링되는지 확인하세요: 필드가 레이아웃 내에 표시되고, 간격을 존중하며, 양쪽 플랫폼에서 열리는지 확인하세요.
- 입력 경로가 정확한가요: NativeBase 프로젝트는 종종 기존 컴포넌트 API와 새로운 API를 혼합하여 오래된 이유로 실패합니다.
- 선택된 값이 제어되는지 확인하세요: 조립품 프로토 타입이든 간에,
selectedValue상태에서부터 사용하세요. code가 이후 디버깅이 어려워질 수 있습니다.
실용적인 규칙: 서버 데이터, placeholder 규칙, 분석 Hook, 유효성 검사 Hook를 동일한 픽커에 매핑하지 마세요. 먼저 컴포넌트를 표시하고 제어하세요.
기본적인 baseline이 중요합니다. Android가 이후 이상하게 동작할 때, 문제가 전체 폼 아키텍처가 아니라 픽커 때문인지 알 수 있습니다.
상태와 선택을 처리하는 방법
픽커가 렌더링되면, 다음 작업은 픽커를 유용하게 만드는 것입니다. React Native에서, 이는 선택된 값을 컴포넌트 상태에 저장하고, 선택된 값을 컴포넌트에 전달하는 것입니다.
표준 경로는 직관적입니다. 현재 값을 저장하고, useStatepass it into selectedValue그리고 업데이트 된 상태를 내장하세요. onValueChange이것은 다른 형식의 입력 필드와 같은 React Native TextInput 패턴을 사용하는 것과 같습니다.
사용자 인터페이스 제어를 사용하여부터 시작하세요.
이것이 유효성 검사나 부수 효과를 추가하기 전에 사용할 수 있는 깨끗한 버전입니다.
import React, { useState } from 'react';
import { Text } from 'react-native';
import { Form, Item, Picker } from 'native-base';
export default function RolePicker() {
const [role, setRole] = useState('');
return (
<>
<Form>
<Item picker>
<Picker
mode="dropdown"
selectedValue={role}
onValueChange={(value) => setRole(value)}
>
<Picker.Item label="Select a role" value="" />
<Picker.Item label="Admin" value="admin" />
<Picker.Item label="Editor" value="editor" />
<Picker.Item label="Viewer" value="viewer" />
</Picker>
</Item>
</Form>
<Text>Selected role: {role || 'none'}</Text>
</>
);
}
그 code은 예측 가능한 참조 소스를 제공합니다. 사용자 인터페이스는 role와 동일한 상태에서 모든 하류 함수가 읽습니다.
선택 로직을 작고 테스트 가능한 것으로 유지하세요.
문제는 개발자가 한 줄의 인라인 함수에서 데이터를 가져오고 여러 상태 조각을 변형하고 네비게이션을 트리거하고 분석 로그를 기록할 때 발생합니다. onValueChange픽커 동작이 실패할 때 디버깅이 고통스럽습니다.
보다 나은 패턴은 값 저장소와 부수 효과를 분리하는 것입니다.
import React, { useEffect, useState } from 'react';
import { Text } from 'react-native';
import { Form, Item, Picker } from 'native-base';
export default function DepartmentPicker() {
const [department, setDepartment] = useState('');
const [message, setMessage] = useState('No department selected');
useEffect(() => {
if (!department) {
setMessage('No department selected');
return;
}
setMessage(`Department selected: ${department}`);
}, [department]);
return (
<>
<Form>
<Item picker>
<Picker
selectedValue={department}
onValueChange={setDepartment}
>
<Picker.Item label="Select department" value="" />
<Picker.Item label="Sales" value="sales" />
<Picker.Item label="Support" value="support" />
<Picker.Item label="Operations" value="operations" />
</Picker>
</Item>
</Form>
<Text>{message}</Text>
</>
);
}
이 구조는 두 가지 유용한 일을 수행합니다:
- 이 PICKER는 선택 상태를 업데이트하는 것에만 책임이 있습니다.
- 앱의 동작을
useEffect에서 테스트하고 추론할 수 있습니다.
폼 컴포넌트가 선택된 값이 무엇인지 신뢰할 수 없다면, 모든 부수 효과가 의심스럽게 됩니다.
Android에서 NativeBase PICKER의 의도된 이벤트 흐름이 항상 유지되지 않기 때문에 이 점은 중요합니다.
Android에서 onValueChange 버그를 해결하는 방법
이 부분은 대부분의 기사에서 생략됩니다. NativeBase PICKER는 Android에서 보건상 건강해 보이면서도 정확한 순간에 실패할 수 있습니다.
커뮤니티 문서에서 오래된 PICKER 구현에 대한 설명은 실제로 플랫폼 간의 분리가 있습니다. Android에서는 onValueChange를 호출하지 않으면서 iOS에서는를 호출합니다. 그리고 그 실패는 Android에서 0% 성공률로 Android 기기에서 함수 트리거링에 성공하지 못하는 100% 기능 불일치에도 불구하고 동일한 code 구현을 사용함에 따라 문서화된 보고서에서 설명된 것과 같이. 동일한 문서는 개발자에게 대체 방법 또는 마이그레이션을 제안하고 NativeBase 3.0 Select 컴포넌트가 Android 및 iOS 플랫폼에서 테스트 환경에서 테스트된 환경에서 98% 함수 트리거링 성공률을 달성함에 따라 비교를 위해 NativeBase picker 문서 및 마이그레이션 컨텍스트에서 설명된 것과 같이 NativeBase Picker 컴포넌트의 Android에서 발생하는 일반적인 버그와 그 해결책을 설명하는 인포그래픽입니다..

Android에서 NativeBase Picker는 native 스플리너에 의존하고, 많은 개발자가 기대하는 것과 달리 wrapper에 이벤트 리스너를 전파하지 않는다는 구현 세부 사항이 그 이유입니다. iOS에서는 모달 기반 동작이 이벤트 시스템에 올바르게 바인딩됩니다.
이 버그는 왜 그렇게 속이는지 그 이유입니다. UI를 보실 수 있습니다. 옵션을 열 수 있습니다. thậm chí 선택 가능한 항목을 선택할 수 있습니다. 그러나 사업 기능이 실행되지 않습니다.
일반적인 실패 패턴은 다음과 같습니다.
iOS에서는 의도한대로 동작할 수 있습니다. Android에서는 픽커가 렌더링되지만 함수가 실행되지 않습니다.
<Picker
selectedValue={status}
onValueChange={(value) => {
setStatus(value);
saveStatusToApi(value);
trackSelection(value);
updateDependentFields(value);
}}
>
Android에서 NativeBase Picker 버그의 해결책
생산 환경에서 유지되는 대안
가장 신뢰할 수 있는 대안은 구조적이지 않다. 선택된 값을 저장하는 데 집중하는 픽커 상호 작용을 유지하고, 픽커 핸들러 외부의 상태 변경에 반응하십시오.
import React, { useEffect, useState } from 'react';
import { Form, Item, Picker } from 'native-base';
export default function StatusPicker() {
const [status, setStatus] = useState('');
const [didMount, setDidMount] = useState(false);
useEffect(() => {
if (!didMount) {
setDidMount(true);
return;
}
if (!status) return;
runStatusSideEffects(status);
}, [status, didMount]);
const runStatusSideEffects = (value) => {
console.log('Selected status:', value);
// call validation, API sync, or dependent form updates here
};
return (
<Form>
<Item picker>
<Picker
selectedValue={status}
onValueChange={setStatus}
>
<Picker.Item label="Select status" value="" />
<Picker.Item label="Pending" value="pending" />
<Picker.Item label="Approved" value="approved" />
<Picker.Item label="Rejected" value="rejected" />
</Picker>
</Item>
</Form>
);
}
왜 도움이 되는가?
- 상태가 중앙에 유지됩니다: 컴포넌트 로직은
status, 픽커 이벤트 페이로드만을 감시하지 않습니다. - 사이드 이펙트가 명확해집니다: API 호출, 의존 필드 업데이트 및 추적이 더 이상 약한 UI 콜백 내에서 살아남지 않습니다.
- code를 더 쉽게 교체할 수 있습니다: NativeBase 픽커로 이주하는 경우 대부분의 비즈니스 로직이 손상되지 않고 살아남습니다.
Android-heavy 프로젝트의 경우, NativeBase Picker와의 이주를 고려할 때, 특히 이미 NativeBase Picker를 사용하는 앱이 NativeBase Picker를 사용하는 경우, NativeBase Picker를 사용하는 앱의 Android 설정이 복잡한 경우, 실제 기기에서 테스트하는 것을 권장합니다. Android 설정을 위한 Capacitor 앱.
Select로 마이그레이션하는 것이 더 깨끗한 결정일 때
픽커가 체크아웃, 온보딩, 또는 규제 데이터 입력과 같은 крит적인 워크플로 내에 위치한다면, 이전 동작을 대체하는 대신 픽커를 업데이트하는 것은 가치가 없을 수 있습니다. 그 시점에서 NativeBase 3.0으로 이동하는 것이 보다 안전한 장기적인 선택입니다. Select 버그는 단순히 불편함만이 아닙니다. 이는 비즈니스 로직을 안전하게 위치할 수 있는 곳을 변경합니다.
픽커를 유지하는 것은 UI 셸로 간주하고 최소한의 책임만을 지는 것입니다. 이러한 마음가짐은 많은 silent Android regressions를 방지합니다.
픽커 컴포넌트의 스타일링 및 테마링
작동하는 픽커라도 앱의 나머지 부분과 일치하지 않으면 아직도 완성되지 않은 느낌을 주게 됩니다. NativeBase는 컨트롤이 의도된 것처럼 느끼게 해주는 충분한 hook를 제공하지만, 픽커를 직접 싸고 싶지 않다면 픽커 자체를 직접 싸는 대신 컨테이너를 스타일링하는 것이 가장 깨끗한 결과를 얻을 수 있습니다.
휴대폰을 잡고 있는 손과 여행 예약 앱에 native base 픽커 드롭다운 메뉴가 표시된 사진.

픽커 자체는 부분적으로 네이티브 렌더링에 의해 제한됩니다. 컨테이너는 픽커에 대한 공간, 테두리 처리, 레이아웃 리듬에 대한 훨씬 더 많은 제어권을 제공합니다.
실용적인 패턴:
이 접근 방식은 일반적으로 테마 오버라이드에 대한 과도한 엔지니어링을 피하면서 대부분의 방법을 제공합니다.
import React, { useState } from 'react';
import { StyleSheet } from 'react-native';
import { Form, Item, Picker, Icon } from 'native-base';
export default function StyledPicker() {
const [country, setCountry] = useState('');
return (
<Form>
<Item style={styles.pickerWrapper} picker>
<Picker
mode="dropdown"
iosIcon={<Icon name="arrow-down" style={styles.icon} />}
textStyle={styles.pickerText}
selectedValue={country}
onValueChange={setCountry}
>
<Picker.Item label="Select country" value="" />
<Picker.Item label="Germany" value="de" />
<Picker.Item label="Japan" value="jp" />
<Picker.Item label="Brazil" value="br" />
</Picker>
</Item>
</Form>
);
}
const styles = StyleSheet.create({
pickerWrapper: {
borderWidth: 1,
borderColor: '#D1D5DB',
borderRadius: 10,
marginTop: 12,
paddingLeft: 8,
backgroundColor: '#FFFFFF',
},
pickerText: {
color: '#111827',
fontSize: 16,
},
icon: {
color: '#111827',
fontSize: 18,
},
});
A hand holding a smartphone displaying a travel booking app with a native base picker dropdown menu.
플랫폼에 맞는 표현을 사용하세요.
iOS와 Android는 거의 동일한 스타일링이 필요하지 않습니다. 동일한 시각적 토큰이 여전히 다른 패딩, 아이콘 배치 또는 픽커 모드가 필요할 수 있습니다.
유용한 조정 사항은 다음과 같습니다.
- iOS에서: 필드에 여유를 주고 모달 표시가 주변 레이블과 관련된지 주의하세요.
- Android에서: 다양한 기기에서 텍스트 클리핑 및 기본 스피너 높이를 확인하세요.
- 두 경우 모두: 장치 선택을 구별하기 위한 장치 선택 텍스트를 시각적으로 구분하세요.
짧은 비교가 도움이 됩니다.
| 관심사 | iOS | 안드로이드 |
|---|---|---|
| 열거형 행동 | 모달 느낌 | 스피너 느낌 |
| 아이콘 예상 | 많이 장식적인 경우 | 많이 기능적인 경우 |
| 간격 문제 | 프레이스 홀더 레이아웃이 느슨한 느낌을 줄 수 있습니다. | 텍스트가 꽉 차있는 느낌을 줄 수 있습니다. |
UI에 그라디언트, 층별 카드 또는 고대비 표면이 포함되어 있다면, 픽커 wrapper를 동일한 처리를 사용하는 인터페이스에서 사용하는 것과 같은 패턴을 사용하여 정렬하십시오. 리액트 네이티브 선형 그라디언트 UI 작업에서 사용하는 것과 같은 패턴을 사용하십시오..
설계 주의사항: 사용자는 드롭다운 자체보다 폼 내에 닫힌 field가 어떻게 들어가 있는지에 더 많은 판단을 내립니다.
그것이 왜 border radius, label spacing, placeholder color가 더 중요한 것인지 이해하는 것이 중요합니다.
고급 시나리오 및最佳 관행
대부분의 픽커 버그는 프로토 타입 단계를 벗어나면 나타납니다. 문제는 옵션이 서버에서 오고, 유효성 검사 규칙이 플랫폼에 따라 다르고, placeholder가 유효한 값처럼 행동할 수 없을 때 시작됩니다.
iOS에서 특히 반복되는 한 가지 edge case가 매우 불편합니다. 개발자들은 종종 서버에서 픽커 값을 로드해야 하며, placeholder 항목이 선택할 수 없도록 방지해야 합니다. 그러나 공식 자료가 그 경로를 직접적으로 다루지 않는 경우가 많습니다. 커뮤니티 토론은 placeholder 값이 iOS에서 선택할 수 있게 남아 있는 경우가 많다는 것을 강조합니다.이것이 React Native 커뮤니티 토론에서 서버 로드 픽커 값과 placeholder 선택에 대한 문제를 언급한 것입니다..

서버 데이터에서 픽커 옵션을 안전하게 로드하는 방법
나는 가장 자주 보는 실수 중 하나가 fetched 데이터를 즉시 픽커 준비 상태로 취급하는 것이라고 생각합니다. API 응답과 컴포넌트 사이에 작은 변환层를 유지하는 것이 중요합니다.
import React, { useEffect, useState } from 'react';
import { Form, Item, Picker } from 'native-base';
export default function DynamicCategoryPicker() {
const [categories, setCategories] = useState([]);
const [selectedCategory, setSelectedCategory] = useState('');
useEffect(() => {
const loadCategories = async () => {
const response = await fetch('https://example.com/api/categories');
const data = await response.json();
const formatted = data.map((item) => ({
label: item.name,
value: String(item.id),
}));
setCategories(formatted);
};
loadCategories();
}, []);
return (
<Form>
<Item picker>
<Picker
selectedValue={selectedCategory}
onValueChange={setSelectedCategory}
>
<Picker.Item label="Select category" value="" />
{categories.map((item) => (
<Picker.Item
key={item.value}
label={item.label}
value={item.value}
/>
))}
</Picker>
</Item>
</Form>
);
}
그런 형식 단계는 안정적인 계약을 제공합니다. 선택기가 API의 내부 형태를 알 필요가 없습니다.
iOS에서 placeholder 선택 방지
가장 안전한 규칙은 간단합니다. placeholder를 실제 옵션으로 다루지 마십시오. UI 라이브러리에서 그것을 렌더링하기 쉽게 만드는 것과 관계없이.
실용적인 패턴:
- 빈 보초 값 사용: __CAPGO_KEEP_0__의 값으로 유지하거나
''또는 다른 유효하지 않은 애플리케이션 값. - 제출하기 전에 유효성 검사: UI에서만 아니라, placeholder가 선택된 경우에도 양식 유효성 검사에서 빈 값을 거부하십시오.
- 다운스트림 액션 비활성화: placeholder가 선택된 경우 submit 버튼을 비활성화하십시오.
더 엄격한 흐름에서, placeholder가 선택된 경우 helper 텍스트 렌더링:
const isValidSelection = selectedCategory !== '';
그런 다음 액션 버튼을 게이트하거나 API 호출을 해당 조건에 대신 하세요. picker 표시를 믿지 마세요.
접근성 및 생산 습관
Pickers는 접근성 검토를 통과하기 쉽게 native-looking입니다. 그러나 clear labeling과 predictable state가 필요합니다.
몇 가지 습관이 빠르게 성과를 내줍니다.
- 접근성 레이블을 추가하세요. 스크린 리더가 필드를 이해할 수 있도록 하세요.
- 레이블이 명확해야 합니다. ‘Country’보다는 ‘Select’보다 낫습니다.
- 상태 복원 테스트를 작성하세요. 폼을 다시 열고 이전에 선택한 항목이 올바르게 나타나는지 확인하세요.
- 선택에 의한 논리와 관련된 단위 테스트를 작성하세요. UI 외부의 논리가 가장 중요합니다. React 동작 테스트 상태 전환을 보호하는 데 도움이 됩니다.
픽커 자체는 거의 비즈니스 крит적인 경우가 없습니다. 일반적으로 뒤에 있는 상태 변경이 중요합니다.
상태 전환을 보호하는 데 중요한 마음가짐입니다. NativeBase Picker를 입력 표면으로 다루세요. 실제 규칙은 상태, 유효성 검사, 제출 흐름에 두세요.
결론
NativeBase Picker는 깨지기 쉬운 콜백 함수에서 비즈니스 로직을 빼내서 상태 주도 효과로 옮기는 것이 중요합니다. Android 이벤트 처리는 특히 중요합니다. 픽커가 렌더링되기만 하면 신뢰할 수 없습니다.
오래된 코드베이스의 경우, 이 대안은 충분합니다. 중요한 흐름의 경우, Select 로 마이그레이션하는 것이 보다 좋은 투자입니다.
If your team ships Capacitor or Electron apps and wants to push JavaScript, CSS, copy, config, and asset fixes without waiting for store review, Capgo 또는 Electron 앱을 개발하는 팀이 JavaScript, CSS, 복사본, 설정, 및 자산 수정을 스토어 리뷰를 기다리지 않고 푸시하고 싶다면, __CAPGO_KEEP_0__