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

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

React NativeでNative Base Pickerを実装する方法。セットアップ、状態、スタイリング、そしてAndroidでonValueChangeのバグを修正する方法について説明します。

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

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

コンテンツマーケター

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

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

そのギャップは、NativeBase Pickerがまだ経験豊富な開発者を驚かせる原因です。セットアップは簡単、スタイリングは管理可能ですが、生産性の高い信頼性は、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を組み合わせた場合など、面倒な理由で失敗することがよくあります。
  • 選択された値が制御されているかどうか: 即席のプロトタイプでも、 selectedValue から状態を使用するようにしてください。未制御のピッカーcodeは、後でデバッグするのが難しくなります。

実用的なルール: サーバーデータ、プレースホルダー規則、アナリティクスハック、バリデーションを同じピッカーにマッピングするのではなく、まずコンポーネントを表示し、制御することから始めましょう。

基準を削減したものは重要です。Androidが後で不正行為を始める場合、フォームアーキテクチャ全体が問題であると考えるのではなく、ピッカーが原因であることを知ることができます。

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

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

標準のパスは簡単です。 useState現在の値を保存して 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, そして、すべての下流の関数は同じ状態から読み取る

選択ロジックを小さくテスト可能にします

問題は、開発者が一つのインライン関数でデータを取得し、複数の状態スライスを変更し、ナビゲーションをトリガーし、分析をログすることから始まることが多い onValueChangeそれらの側面を分離することによって、値の保存と副作用を分離することによって、より良いパターンが得られる

副作用を分離することによって、開発者は、UIの更新とデータの取得を分離し、開発を容易にすることができる

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ピッカーのドキュメントと移行コンテキストに記載されているように、

<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で使用するダイナミックピッカーのデータフロープロセスを示す図。

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 !== '';

アクションボタンのゲートまたはAPIの呼び出しは、その条件に基づいて実行されるのではなく、ピッカーの表示を信頼するのではなく。

アクセシビリティと実稼働の慣習

ピッカーは、ネイティブな見た目を持っているため、アクセシビリティのレビューから漏れがちですが、明確なラベル付けと予測可能な状態が必要です。

いくつかの習慣は、すぐに効果を発揮します。

  • アクセシビリティのラベルを追加する スクリーンリーダーでフィールドを理解できるようにする
  • ラベルを明確にする “Country” is better than “Select”.
  • テストの状態の復元 フォームを再開し、以前選択されたアイテムが正しく表示されていることを確認する
  • 選択に基づくロジックを取り巻くユニットテストを書く UI外側のロジックは最も重要であり、 unit testing React の動作 __CAPGO_KEEP_0__ を保護するために、状態の移行を助けています。

Picker 自体はまれにビジネスクリティカルです。背後にある状態の変更が重要です。

動的フォームを安定させるのは、NativeBase Picker を入力面とみなすことです。実際のルールは、状態、検証、サブミッションフローに置きます。

結論

NativeBase Picker は、破綻を理解している場合にまだ有用です。セットアップは簡単、スタイリングは可能、サーバーからドライブされたオプションリストは管理可能です。ただし、Android イベントハンドリングは重要な罠です。フラグレートなピッカーのコールバックからビジネスロジックを取り除き、状態駆動のエフェクトに移すと、コンポーネントは予測可能になります。

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


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

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

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

今すぐ始めましょう

ブログの最新記事

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