본 콘텐츠로 건너뛰기

리액트 네이티브에서 네이티브 베이스 픽커를 구현하는 방법

마틴 도나디우

네이티브 베이스 픽커: 설정, 스타일링 & 안드로이드 고정

네이티브 베이스 픽커와 같은 벽을 여러 번 맞은 React Native 팀이 있을 것입니다. 드롭다운이 렌더링되며, iOS는 정상 작동하지만 안드로이드는 논리와 관련된 오류를 무시합니다. onValueChange 이런 벽을 넘어서는 네이티브 베이스 픽커는 경험 많은 개발자들을 놀라게 합니다. 설정은 간단하고 스타일링은 관리가 가능하지만, 프로덕션의 신뢰성은 안드로이드에 특정한 오류를 이해하는 데에 달려 있습니다.

내용목록

네이티브 베이스 픽커를 사용하는 방법

NativeBase 픽커와 시작하기

A picker는 일반적으로 스프린트의 마지막에 추가하는 컴포넌트 중 하나입니다. 국가 선택기, 상태 필드, 약속 유형, 배송 옵션. 플랫폼 동작이 UI에 유출되기 시작할 때까지 작게 느껴집니다.

Native Base Picker 네이티브 베이스 픽커 NativeBase Picker은 iOS와 Android에서 네이티브 픽커를 렌더링하고 deprecated React Native Picker을 더 오래된 NativeBase 설정에서 대체하기 위해 만들어졌습니다. 따라서 많은 레거시 코드베이스가 여전히 그것을 사용하고 있습니다.

개발자 작업 환경으로 React Native code를 보여주는 노트북과 모바일 앱 인터페이스가 있는 장면입니다.

정상적인 React Native 설정에서 컴포넌트를 설치하십시오.

NativeBase를 이미 사용하는 프로젝트의 경우, 주된 작업은 올바른 원초체를 가져오고 일일이 wrapper logic를 피하는 것입니다. 첫 번째 뷰어블 픽커부터 시작하십시오.

모바일과 하이브리드 스택을 동시에 작업하는 경우, React code이 더 광범위한 환경인 React mobile app workflows code에 어떻게 패키징되는지 이해하는 것도 도움이 됩니다. 픽커 code는 익숙하지만 배포 기대치는 달라집니다. React mobile app workflows with Capacitor. The picker code stays familiar, but deployment expectations change.

Render a first picker without extra abstraction

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 from state. 비제어된 픽커 code는 나중에 디버깅하기 더 어려워집니다.

실용적인 규칙: 서버 데이터, placeholder 규칙, 분석 Hook, 유효성 검사 Hook를 동일한 픽커에 매핑하지 마세요. 먼저 컴포넌트가 보이도록 하고 제어되도록 하세요.

그것은 스트리핑된 기본선이 중요합니다. Android가 나중에 이상하게 행동할 때, 그 문제가 전체 폼 아키텍처가 아니라 픽커 때문인지 알 수 있습니다.

상태와 선택을 처리하는 방법

픽커가 렌더링되면 다음 작업은 그것이 유용하도록 만드는 것입니다. React Native에서 그것을 제어된 입력으로 다루고 선택된 값을 컴포넌트 상태에 저장하는 것입니다.

표준 경로는 직관적입니다. 현재 값을 저장하고 useState를 호출하고 selectedValue를 호출하여 상태를 업데이트합니다. 다른 형식 필드와 마찬가지로 이 마음가짐을 사용합니다. onValueChangeReact Native TextInput 패턴 UI 제어는 다르지만.제어된 값을 처음부터 사용하세요

유효성 검사나 부수 효과를 추가하기 전에 사용할 수 있는 깨끗한 버전입니다.

그 __CAPGO_KEEP_0__는 예측 가능한 참조 소스를 제공합니다. UI는

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이 제공하는 예측 가능한 진실의 근거를 통해 UI는 반영됩니다. role선택 로직을 작고 테스트 가능한 것으로 유지하세요

이미지

개발자들이 오버로드를 할 때 일반적으로 문제가 시작됩니다. onValueChange그들은 데이터를 가져오고, 여러 상태 조각을 변형하고, 내비게이션을 트리거하고, 분석을 로깅하는 일회성 함수를 호출합니다.

이러한 패턴은 개발자가 picker의 동작을 이해하기 어렵게 만들 수 있습니다.

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>
    </>
  );
}

더 나은 패턴은 값 저장을 효과 부여에서 분리하는 것입니다.

  1. 이 구조는 두 가지 유용한 일을 수행합니다.
  2. 픽커는 선택 상태만 업데이트하는 책임만을 지게 됩니다. useEffect앱의 동작은

에서 테스트하고 논리적으로 생각할 수 있습니다.

폼 컴포넌트가 선택된 값을 신뢰할 수 없다면, 모든 효과가 의심스럽게 됩니다.

이 점은 안드로이드에서 특히 중요합니다.

NativeBase Picker의 의도된 이벤트 흐름이 항상 유지되지 않기 때문입니다.

안드로이드에서 ValueChange 버그를 해결하는 방법입니다. Android는 사용자 정의 함수에 연결된 함수를 트리거하지 않습니다. onValueChangeiOS는 그렇지 않습니다., 그리고 그 실패는 described as a} 100% functional disparity on Android with a 0% success rate for function triggering on Android devices despite identical code implementation 100%의 Android 기능 불일치와 0%의 Android 장치에서 함수 트리거 성공률이 동일한 implementation __CAPGO_KEEP_0__에 대해 문서화된 보고서에서 설명합니다. Select 동일한 문서는 개발자에게 대체 방법 또는 마이그레이션을 제안하고, NativeBase 3.0 component가 테스트 환경에서 98%의 함수 트리거 성공률을 달성하는 NativeBase Picker의 98%의 기능 불일치와 비교합니다. NativeBase Picker 문서 및 마이그레이션 컨텍스트에서 설명합니다. NativeBase Picker 컴포넌트의 일반적인 버그에 대한 설명서입니다. Android에서 실제로 무엇이 깨지나요?.

Android에서 NativeBase Picker의 Native Spinner에 의존하고, wrapper에 이벤트 리스너를 전파하지 않습니다.

iOS에서는 NativeBase Picker의 모달 기반 동작을 통해 이벤트 시스템에 바인딩이 됩니다.

NativeBase Picker의 Native Spinner에 의존하고, wrapper에 이벤트 리스너를 전파하지 않습니다.

이 버그는 왜 그렇게 속이는 것처럼 느껴질까? UI를 보이고 옵션을 열 수 있고, 선택 가능한 항목을 선택할 수도 있지만, 비즈니스 함수는 실행되지 않는다.

일반적인 실패 패턴은 다음과 같다.

<Picker
  selectedValue={status}
  onValueChange={(value) => {
    setStatus(value);
    saveStatusToApi(value);
    trackSelection(value);
    updateDependentFields(value);
  }}
>

iOS에서는 예상대로 동작할 수 있지만, Android에서는 픽커가 렌더링되면서 함수가 실행되지 않는다.

생산 환경에서 유지되는 대안

가장 신뢰할 수 있는 대안은 아키텍처적인 대안이 아닌 외관적인 대안이다. 픽커 상호 작용을 선택한 값을 저장하는 것으로 유지하고, 픽커 핸들러 외부의 상태 변경에 반응한다.

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 Picker로 이주하지 않는 경우, 대부분의 비즈니스 로직이 손상되지 않습니다.

Android-heavy 프로젝트의 경우, 실제 장치에서 테스트하는 것을 추천합니다. 특히 앱이 native 패키징 복잡성을 가지고 있다면, 특히 Android 설정을 위한 Capacitor 앱.

Select로 이주하는 것이 더 깨끗한 결정입니다.

픽커가 중요한 워크플로우에 위치하고 있다면, 예를 들어 체크아웃, 온보딩, 규제 데이터 입력과 같은 경우, 이전 동작을 대체하는 것은 가치가 없습니다. 그 시점에서 NativeBase 3.0으로 이주하는 것이 보다 안전한 장기적인 선택입니다. Select 버그는 단순히 불편함만이 아닙니다. 비즈니스 로직을 안전하게 위치할 수 있는 곳을 변경합니다.

픽커를 유지하는 경우, 픽커를 UI 셸로 간주하고 최소한의 책임을 부여하는 마음-set을 유지하세요. 이러한 마음-set은 많은 silent Android regressions를 방지합니다.

픽커 스타일링 및 테마링

선택 컴포넌트 스타일링 및 테마링

손으로 휴대폰을 잡고 있는 손으로 여행 예약 앱을 보여주는 이미지.

컨테이너를 스타일링하기 전에 픽커를 스타일링하세요.

Wrapper 스타일을 먼저 설정한 후 PICKER 스타일을 설정하세요.

자체 픽커는 부분적으로 원시 렌더링에 의해 제한됩니다. wrapper는 간격, 테두리 처리 및 레이아웃 리듬에 대한 더 많은 제어를 제공합니다.

실용적인 패턴:

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,
  },
});

그런 접근 방식은 일반적으로 테마 오버라이드의 과도한 엔지니어링을 피하면서 대부분의 경우에 성공합니다.

플랫폼에 대한 표시를 사용하십시오

iOS와 Android는 거의 동일한 스타일링이 필요하지 않습니다. 일관된 의도만 필요합니다. 동일한 시각적 토큰은 여전히 다른 패딩, 아이콘 배치 또는 픽커 모드가 필요할 수 있습니다.

유용한 조정 사항은 다음과 같습니다:

  • iOS에서: 필드에 숨겨진 공간을 주고 모달 표시가 주변 레이블과 어떻게 관련되는지 주의하십시오.
  • Android에서: 여러 기기에서 텍스트 클리핑 및 기본 스피너 높이를 확인하십시오.
  • 두 경우 모두: 장치 선택과 실제 선택을 구별하는 데 도움이 되는 장치 텍스트를 유지하십시오.

간단한 비교는 도움이 됩니다:

관심사 iOS 안드로이드
열기 동작 모달 느낌 스피너 느낌
아이콘 기대 많이 장식적인 경우 많이 기능적인 경우
간격 문제 대체 레이아웃이 느슨한 느낌 텍스트는 느슨해질 수 있습니다.

UI에 그라디언트, 층화된 카드, 또는 고대비 표면이 포함되어 있다면, 픽커 wrapper를 동일한 처리를 사용하는 인터페이스에서 사용하는 것과 같이 패턴을 사용하여 정렬하십시오. 디자인 주의사항:.

사용자는 픽커 자체를 더 많이 평가하지 않고, 닫힌 field가 폼 내부에 어떻게 위치하는지에 더 많이 집중합니다. 그런 이유로, 테두리 반지름, 레이블 간격, 그리고 placeholder 색상이 더 중요한 요소입니다.

고급 시나리오 및 최적화 방법

고급 시나리오 및 최적화 방법

iOS에서 특히 짜증스러운 반복되는 에지 케이스는 개발자가 서버에서 픽커 값을 로드하는 동안 placeholder 항목이 선택할 수 없도록 방지해야 한다는 것입니다. 그러나 공식적인 자료가 그 경로를 직접적으로 다루지 않는 경우가 많습니다.

커뮤니티 토론에서, placeholder 값이 iOS에서 선택할 수 있는 상태로 남아 있는 경우가 종종 발생합니다. , 이는 실제 앱에서 일관된 동작이 불가능하게 만드는 결과를 낳습니다.이러한 문제에 대한 토론은 React Native 커뮤니티에서 서버 로드된 픽커 값과 placeholder 선택에 대한 토론입니다. 서버 로드된 픽커 값과 placeholder 선택에 대한 토론.

NativeBase Picker를 사용하는 네이티브 데이터 흐름의 네 단계 다이어그램입니다.

서버 데이터로부터 피커 옵션을 안전하게 로드하세요.

가장 흔히 하는 실수는 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에서 플레이스 홀더 선택을 방지하세요.

가장 안전한 규칙은 간단합니다. 플레이스 홀더를 실제 옵션으로 간주하지 마십시오, 심지어 UI 라이브러리가 쉽게 렌더링할 수 있더라도.

실용적인 패턴:

  • 빈 시그널 값을 사용하세요: __CAPGO_KEEP_0__의 플레이스 홀더 값을 유지하세요 '' 또는 다른 유효하지 않은 애플리케이션 값을 사용하세요.
  • 제출하기 전에 검증하세요: 빈 값을 폼 검증에서 거부하세요, 단지 UI에서만 거부하지 마십시오.
  • 다운스트림 동작을 비활성화하세요: 제출 버튼을 활성화하기 전에 비어 있지 않은 값이 있는지 확인하세요.

더 엄격한 흐름을 위해, placeholder가 선택된 경우 helper 텍스트를 렌더링하세요:

const isValidSelection = selectedCategory !== '';

그런 다음 picker 표시를 신뢰하지 않고 action 버튼이나 API 호출을 조건에 따라 게이트하세요.

접근성 및 생산성 습관

픽커는 접근성 검토를 통과하기 쉽지만, 명확한 레이블링 및 예측 가능한 상태가 필요합니다.

몇 가지 습관이 빠르게 성과를 낼 것입니다:

  • 접근성 레이블을 추가하세요: 스크린 리더가 field를 이해할 수 있도록 하세요.
  • 레이블을 명확하게 유지하세요: ‘Country’보다는 ‘Select’보다 낫습니다.
  • 상태 복원 테스트를 진행하세요. 다시 열어보면 이전에 선택한 항목이 올바르게 표시되는지 확인하세요.
  • 선택에 따라 로직을 테스트하는 단위 테스트를 작성하세요. UI 외부의 로직이 가장 중요하고 React 동작을 테스트하는 단위 테스트가 상태 전환을 보호하는 데 도움이 됩니다. 픽커 자체는 거의 비즈니스 крит적인 경우가 드물다. 뒤에 있는 상태 변경이 중요합니다.

그것이 동적 폼을 안정적으로 유지하는 마음가짐입니다. NativeBase Picker를 입력 표면으로 다루세요. 실제 규칙은 상태, 유효성 검사, 제출 흐름에 두세요.

결론

Conclusion

오래된 코드베이스의 경우, 그 workaround만으로 충분합니다. 중요한 흐름의 경우, migrate하는 것이 보통 더 좋은 투자입니다. 그 방법은 같습니다. picker를 믿지 마세요. 단지 렌더링만 되면 충분하지 않습니다.

팀이 __CAPGO_KEEP_0__ 또는 Electron 앱을 배포하고 JavaScript, CSS, 복사본, 구성, 자산 수정을 스토어 리뷰 기다리지 않고 푸시하고 싶다면 Select Live Update


애플리케이션을 배포하는 팀이 Capacitor 또는 Electron 앱을 개발하고 스토어 리뷰를 기다리지 않고 JavaScript, CSS, 복사본, 설정, 및 자산 수정을 푸시하고 싶다면 Capgo Live Update를 사용하면 signed live updates, rollout control, rollback protection, 및 release visibility를 제공하여 UI 버그와 같은 픽커 회귀가 프로덕션으로 도망치기 전에 더 빠르게 복구할 수 있습니다.

Capacitor 앱에 대한 즉시 업데이트

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

웹层 버그가 활성화된 경우 __CAPGO_KEEP_0__를 통해修정을 배포하는 대신 앱 스토어 승인까지 며칠 기다리지 말고 배포하세요. 사용자는 배경에서 업데이트를 받으면서 네이티브 변경 사항은 일반적인 검토 경로에 남아 있습니다.

페이지/영역: Capgo 마케팅 웹사이트. 역할: 지원 설명 문장 또는 메타 설명. 보는 곳: 컴포넌트 GetStarted.astro. Capgo 제품/브랜드 및 개발자 용어를 정확히 유지하십시오.

마틴의 인간 지원

Capgo은 전문적인 모바일 앱을 만들기 위해 필요한 최고의 통찰력을 제공합니다.