メインコンテンツにジャンプ

Native Base Picker: セットアップ、スタイリング & Android修正

React NativeでNative Base Pickerを実装する方法。セットアップ、状態、スタイリング、そしてAndroidでonValueChangeバグの重要な修正をカバーするクイックガイドです。

マーティン・ドナディュー

マーティン・ドナディュー

コンテンツマーケター

Native Base Picker: セットアップ、スタイリング & Android修正

React NativeチームがNativeBase Pickerで遭遇する壁にあなたもたどり着いたことはありませんか。ドロップダウンは表示され、iOSは正常に動作し、Androidはあなたの onValueChange 論理を無視します。クラッシュはありません。警告もありません。ただし、機能しているように見えるピッカーがあなたのビジネスロジックを実行することはありません。

NativeBase ピッカーのそのギャップは、経験豊富な開発者にとってまだ驚きの要因です。セットアップは簡単、スタイリングは管理可能ですが、生産性の安定性は、Android固有のエラーを理解することによってのみ実現されます。Android固有のエラーは、ほとんどのガイドでは省略または言及されていません。

目次

NativeBase ピッカーの使用開始

通常、ピッカーはスプリントの後半に追加されるコンポーネントです。国選択、ステータスフィールド、予定時刻、発送オプション。プラットフォームの動作がUIに漏れ出すまで、感じるのは小さなものです。

いいニュースは NativeBase ピッカー 画面上で簡単に表示できます。iOSとAndroidでネイティブのピッカーをレンダリングし、古いNativeBaseのセットアップで非推奨のReact Nativeピッカーを置き換えるように設計されています。なぜなら、多くのレガシーコードベースはそれに依存しているからです。

開発者用ワークスペースは、React Native codeとモバイルアプリケーションインターフェイスの横に表示されるノートパソコンを特徴としています。

通常のReact Nativeセットアップでコンポーネントをインストールします。

NativeBaseをすでに使用しているプロジェクトの場合、主なタスクは、必要な原子をインポートし、初日から不要なラッパーロジックを避けることです。最もシンプルな可視ピッカーから始めましょう。

モバイルとハイブリッドスタックを横断して作業している場合、より広い環境であるReact codeがパッケージ化される方法を理解することも役立ちます。 Reactモバイルアプリワークフローに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>
  );
}

抽象化なしで最初のピッカーをレンダリングします。

最初のパスでは、次の2つの質問に答えるだけです。

  • 正しくレンダリングされるかどうか: フィールドがレイアウト内に表示され、スペースを尊重し、両方のプラットフォームで開くかどうかを確認したいと思います。
  • インポートパスが正しいですか: NativeBaseプロジェクトは、古いコンポーネントAPIと新しいコンポーネントAPIを組み合わせた場合など、面倒な理由で失敗することがよくあります。
  • 選択された値が制御されているか: 即席のプロトタイプでも、__CAPGO_KEEP_0__から状態を使用することです。制御されていないピッカーは、後でデバッグするのが難しくなります。 selectedValue from state. Uncontrolled picker code becomes harder to debug later.

まず、サーバーデータ、プレースホルダー規則、アナリティクスハック、バリデーションを同じピッカーにマッピングしないでください。コンポーネントが表示され、制御されていることを確認してください。 基本的なベースラインは重要です。Androidが後で不正行為を始めた場合、問題はフォームアーキテクチャ全体ではなく、ピッカーだけです。

状態のバインディングと選択のハンドリング

ピッカーがレンダリングされたら、次の仕事はそれを有用にすることです。React Nativeでは、それを制御された入力として扱い、選択された値をコンポーネントの状態に保存することです。

標準的なパスは簡単です。現在の値を保存し、

選択された値をコンポーネントの状態に保存することです。 useState__CAPGO_KEEP_0__ selectedValue、状態を更新する。 onValueChangeこのアプローチは、他のフォームフィールドの場合と同様の考え方を使用します。 例えば、React Native TextInput パターン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、そして、すべての下流の関数は同じ状態から読み取ることができます。

選択ロジックを小さくテストしやすくする

問題は、開発者が一つのインライン関数でデータを取得し、複数の状態スライスを変更し、ナビゲーションをトリガーし、分析をログインすることから始まることが多い。 onValueChangeUI ピッカーの動作が失敗すると、デバッグが苦痛になる。

より良いパターンは、値の保存と副作用を分離することです。

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

この構造体は、2つの有用な機能を実行します:

  1. これにより、ピッカーは選択状態の更新のみを担当し、
  2. アプリの動作は useEffectここで、選択した値がアプリにわかるようにテストし、推論することができます。

フォームコンポーネントが、選択された値を信頼できるようにアプリに伝えることができない場合、すべての副作用が疑問視されます。

Androidでは、NativeBase ピッカーの意図されたイベントフローが常に機能しないため、この点は重要になります。

Android上のonValueChangeのバグのトラブルシューティング

この部分は、ほとんどの記事が省略しています。NativeBase ピッカーはAndroid上で正常に表示されるかもしれませんが、必要な時には機能しないことがあります。

コミュニティドキュメントでは、古いピッカー実装に関するクロスプラットフォームの分割について説明しています。 Androidでは、 onValueChangeをカスタム関数に結び付けることはできませんが、iOSではをカスタム関数に結び付けることができます。 100% functional disparity on Android with a 0% success rate for function triggering on Android devices despite identical code implementation 文書化された報告書では、同様の__CAPGO_KEEP_0__実装にも関わらず、Android上で100%の機能不全が発生します。 Select NativeBase 3.0コンポーネントは、どちらのプラットフォームでもテスト環境で98%の機能トリガー成功率を達成します。 NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように、NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように.

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

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

NativeBaseピッカーのドキュメントと移行コンテキストで説明されているように

実稼動用のワークアラウンド

最も信頼できるワークアラウンドは、外観的なものではなく、設計上のものです。ピッカーのインタラクションは、選択された値を保存することに焦点を当て、ピッカーのハンドラーの外側の状態の変化に反応するようにしてください。

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重視のプロジェクトでは、実機でテストすることをお勧めします。特に、既存のアプリがネイティブパッケージングの複雑さを持つ場合、 Android用のCapacitorアプリの設定.

Selectへの移行は、より綺麗な決定です

重要なワークフローであるチェックアウト、オンボーディング、または規制されたデータ入力の場合、古い動作を修正する代わりに、NativeBase 3.0への移行 Select は通常、長期的な安全な選択です

バグは単に不便さだけではありません。ビジネスロジックを安全に配置する場所が変わります。

古いピッカーを維持する場合は、それをUIシェルとして最小限の責任を持つように扱ってください。この考え方は、静かにAndroidのバグを防ぐのに役立ちます。

ピッカー コンポーネントのスタイリングとテーミング

機能するピッカーでも、他のアプリのデザインに合わない場合は、完成感が感じられません。NativeBaseでは、コントロールが意図的に感じられるように十分なハックを提供しますが、最も綺麗な結果は、ピッカー自体ではなく、ピッカーを囲むコンテナをスタイリングすることです。

スマートフォンを握った手が、旅行予約アプリのネイティブベースピッカーのドロップダウンメニューを表示しています。

コンテナをスタイリングする前にピッカーをスタイリングする

ピッカー自体は、ネイティブレンダリングによって部分的に制限されています。コンテナは、ピッカーのスペース、境界処理、レイアウトリズムの制御を提供します。

実践的なパターン

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の場合 Android
オープンベハビアー モーダルフィール スピナーフィール
アイコンエクスペクテーション しばしば装飾的な しばしば機能的な
スペーシングイシュー プレースホルダーライアウトがゆるい テキストがぎこちなく

UIにグラデーション、レイヤードカード、または高コントラストの表面が含まれている場合、ピッカー・ワッパーを同様の処理で同様のインターフェイスの他の部分と同様に揃えます。 React Nativeの線形グラデーションUIワーク.

設計ノート: ユーザーは、ドロップダウン自体よりも、フォーム内で閉じたフィールドがどのように収まるかでピッカーを評価します。

したがって、ボーダーラジウス、ラベルスペーシング、プレースホルダーカラーは、エキゾチックなピッカーのカスタマイズよりも重要です。

高度なシナリオとベストプラクティス

ほとんどのピッカーのバグは、コンポーネントがプロトタイプフェーズを終了した後に出現します。問題は、オプションがサーバーから来る、バリデーションルールがプラットフォームによって異なる、プレースホルダーの値が有効な値として振る舞えない場合に始まります。

iOS上で特に悩ましいエッジケースが繰り返し発生しています。開発者は、サーバーからピッカーの値をロードする必要がありますが、プレースホルダーのエントリが選択可能になるのを防ぎたいのです。しかし、公式の資料ではそのパスを直接扱っていません。 コミュニティの議論では、プレースホルダーの値がiOS上で選択可能であることが指摘されていますこれが実際のアプリケーションで不一致な動作につながることを示す React Nativeコミュニティの議論.

サーバーからロードされたピッカーの値とプレースホルダーの選択の議論

NativeBaseで使用するダイナミックピッカーの4ステップデータフロープロセスを示す図。

The mistake I see most often is treating fetched data as immediately picker-ready. Keep a small transformation layer between your API response and the component.

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でなくプレースホルダーを拒否する。
  • 下流のアクションを無効にする: プレースホルダー以外の値が存在するまで、送信ボタンを無効にする。

厳格なフローでは、プレースホルダーが選択されたままの場合にヘルプテキストをレンダリングする:

const isValidSelection = selectedCategory !== '';

Then API のアクションボタンをゲートするか、その条件に応じて API を呼び出してください。プレゼンテーションを信頼するのではなく。

アクセシビリティと作業慣行

ピッカーは、ネイティブな見た目でアクセシビリティレビューからすれ違うことがよくあります。ただし、明確なラベルと予測可能な状態が必要です。

いくつかの習慣が早く効果を発揮します。

  • アクセシビリティラベルを追加する: スクリーンリーダーにとってフィールドが理解できるようにする:
  • ラベルを明確にします: 「国」は「選択」よりも良いでしょう。
  • 状態の復元をテストする: フォームを再度開いて、以前選択されたアイテムが正しく表示されることを確認します。
  • 選択に依存するロジックに関してユニットテストを書く: UI外側のロジックが最も重要であり、 unit testing React の動作 __CAPGO_KEEP_0__ を保護するためのステートの移行をサポートします。

ピッカーは単体ではあまりビジネスクリティカルではありません。通常、ピッカーの背後にあるステートの変更がビジネスクリティカルです。

動的フォームを安定させるには、この考え方が重要です。NativeBase ピッカーを入力面として扱い、実際のルールはステート、バリデーション、サブミッションフローに置きましょう。

まとめ

NativeBase ピッカーは、ピッカーが破綻する場所を理解している場合にまだ役立ちます。セットアップは簡単、スタイリングは可能、サーバーからドライブされるオプションリストは管理可能です。ただし、Android イベントハンドリングは重要な罠です。ビジネスロジックを脆弱なピッカーのコールバックからステート駆動のエフェクトに移すことで、コンポーネントの予測性を高めることができます。

古いコードベースの場合、このワークアラウンドはよく機能します。ビジネスクリティカルなフローでは、 Select に移行することが通常より良い投資です。どちらの場合も、同じ鍵があります。ピッカーを信頼するのは、単にレンダリングされるだけです。


チームが Capacitor または Electron アプリをリリースし、JavaScript、CSS、コピー、設定、資産の修正をストアのレビューを待たずに実行したい場合、 Capgo はおすすめです。Signed Live Updates、ロールアウトの制御、ロールバック保護、リリースの可視性を提供して、UI バグのようなピッカーのリグレッションがプロダクションに逃げ込まないように、迅速に回復できます。

リアルタイム更新のCapacitorアプリ

Capgoのバグが実際に生じた場合、Capgoを使用して修正を配信するのではなく、数日間待ってアプリストアの承認を待つのではなく、ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路を通る。

Get Started Now

Latest from our Blog

Capgoは、プロフェッショナルなモバイルアプリを作成するために必要な最良の洞察を提供します。