NativeBase ピッカーで遭遇するであろう、多くの React Native チームが遭遇する壁に遭遇しているかもしれません。ドロップダウンがレンダリングされ、見た目は良好で、iOS は正常に動作し、Android はあなたのロジックを無視します。クラッシュも警告もありません。ただし、ピッカーは機能しているように見えますが、ビジネス ロジックは実行されません。 onValueChange そのギャップは、NativeBase ピッカーが経験豊富な開発者を驚かせる原因です。セットアップは簡単で、スタイリングは管理可能ですが、生産性の高い信頼性は、Android の特定の失敗を理解することによって決まります。多くのガイドでは、この失敗を省略したり、言及しなかったりします。
目次
NativeBase ピッカーの使用開始
- 通常の React Native セットアップでコンポーネントをインストールする
- 制御された値を使用してから始める
- Android の onValueChange バグのトラブルシューティング
- ピッカー コンポーネントのスタイリングとテーミング
- 高度なシナリオとベスト プラクティス
- まとめ
NativeBase ピッカーの使い方
Pickerは通常、スプリントの後半に追加されるコンポーネントの1つです。国選択、ステータスフィールド、アポイントメントタイプ、発送オプション。プラットフォームの動作がUIに漏れ出すまで、感じるのは小さなものです。
良いニュースは NativeBase ピッカー NativeBase Pickerは画面に表示するのが簡単です。iOSとAndroidでネイティブのピッカーをレンダリングし、古いNativeBase設定で非推奨のReact Native Pickerを置き換えるために作られました。そのため、多くのレガシーコードベースは依然としてそれに依存しています。

通常のReact Native設定でコンポーネントをインストールします。
NativeBaseをすでに使用しているプロジェクトの場合、主なタスクは、必要なプリミティブをインポートし、初日から不要なラッパーロジックを避けることです。最もシンプルな可視ピッカーから始めましょう。
モバイルとハイブリッドスタックを横断して作業している場合、React codeがより広い環境である React mobile app workflows with Capacitor. The picker code stays familiar, but deployment expectations change.
抽象化なしで最初のピッカーをレンダリングします
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>
);
}
pickerをレンダリングする
最初のパスでは、2つの質問に答えるようにします:
- 正しくレンダリングされるか: フィールドがレイアウト内に表示され、スペースを尊重し、両方のプラットフォームで開くことを確認します。
- インポートパスが正しいか: ネイティブベースプロジェクトは、古いコンポーネントAPIと新しいコンポーネントAPIを混在させた場合に失敗することがよくあります。
- 選択された値が制御されているか: 即興のプロトタイプでも
selectedValuefrom state. stateを使用しない選択肢 code は、後でデバッグが困難になります。
実用的なルール: サーバーデータ、プレースホルダールール、アナリティクスハック、バリデーションを同一のピッカーにマッピングしないでください。まず、コンポーネントを可視化し、制御することから始めます。
その簡素化された基準は重要です。Androidが後で不正行為を始めた場合、問題はフォームアーキテクチャ全体ではなく、ピッカーだけです。
状態のバインディングと選択の処理
Pickerがレンダリングされたら、次のタスクはそれを有用にすることです。 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>
</>
);
}
Native Base Picker
codeは予測可能な真実の源を提供します。UIはそれを反映しています。 role選択ロジックを小さくテスト可能なものに保つ
targetLanguage
開発者が機能をオーバーロードするときに問題が生じることが多い。 onValueChangeデータを取得し、複数の状態スライスを変更し、ナビゲーションをトリガーし、アナリティクスをログするinline関数を1つにまとめる。
値の保存と副作用を分離するパターンは、より良いものである。
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つの有用な機能を実現する。
- ピッカーは、選択状態を更新する責任のみを持つ。
- アプリの動作は、独立してテストおよび推論できる場所に移動される。
useEffectフォームコンポーネントが、選択された値を信頼できるようにアプリに伝えることができない場合、すべての副作用が疑問視される。
Androidでは、NativeBaseピッカーの意図されたイベントフローが常に機能しないことが多い。
AndroidのonValueChangeバグのトラブルシューティング
この部分は、ほとんどの記事が省略している。
NativeBaseピッカーは、Android上で健康に見えながら、必要な時には機能しない。
コミュニティドキュメントでは、古いピッカー実装のクロスプラットフォーム分離について説明している。 Androidはカスタム関数を onValueChange, しかしiOSは, そしてその失敗はAndroidで Android デバイス上で Android に関する 100% の機能不一致が発生し、0% の成功率で Android デバイス上で機能をトリガーすることに成功したにもかかわらず、同等の code implementation が実装されている。 ドキュメントされたレポートに記載されているものと同じ実装 Select ドキュメントでは、開発者はワークアラウンドまたは移行を指示し、NativeBase 3.0 コンポーネントは 98%の関数トリガー成功率を達成しました。 比較対象は.

NativeBase ピッカー コンポーネントのAndroidにおける一般的なバグとその解決策を示すインフォグラフィックです。
Androidで実際に壊れるのは何かです。
そのため、このバグは欺瞞的であると感じる。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 ピッカーから移行した場合、多くのビジネスロジックは触れられません。
Android重視のプロジェクトでは、実機でテストすることをお勧めします。特に、ネイティブパッケージングの複雑さがあるアプリでは、早期に実機でテストすることをお勧めします。 AndroidのセットアップはCapacitorアプリ用です。.
Selectへの移行はより綺麗な決定です。
ピッカーがチェックアウト、オンボーディング、または規制されたデータエントリの重要なワークフロー内に存在する場合、古い動作を修正する代わりに、NativeBase 3.0への移行がより安全な長期的な選択肢となる場合があります。 Select バグは単に不便なだけでなく、ビジネスロジックを安全に配置できる場所を変更します。
古いピッカーを維持する場合は、それをUIシェルとして最小限の責任を持つように扱ってください。この考え方は、静かにAndroidのバグを防ぐのに役立ちます。
ピッカー コンポーネントのスタイリングとテーミング
パーサー コンポーネントのスタイリングとテーマ設定
スマートフォンを握った手が、旅行予約アプリのネイティブベースピッカーのドロップダウンメニューを表示している。

スタイルをピッカーのラッパーに適用する前にピッカーのスタイルを適用する
Picker自体は、部分的にネイティブレンダリングによって制限されています。ラッパーは、スペーシング、ボーダー処理、レイアウトリズムの制御を大幅に高めます。
実用的なパターン:
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コミュニティディスカッション.

サーバーから安全にピッカーのオプションを読み込む
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ライブラリがそれを簡単にレンダリングできるようにしても。
実践的なパターン:
- 空のシグナル値を使用する: プレースホルダーの値を
''または他の無効なアプリケーション値を保持します。 - 送信前に検証する: 空の値をフォーム検証で拒否するのではなく、UIでだけ拒否しないようにしてください。
- 無効にするダウンストリームアクション: プレースホルダーの値が存在しない場合にまで、サブミットボタンを有効にすることは避けるべきです。
厳密なフローでは、プレースホルダーの値が選択されたままの場合にヘルプテキストを表示するようにしてください。
const isValidSelection = selectedCategory !== '';
次に、条件によってアクションボタンやAPIの呼び出しを制御するのではなく、ピッカーの表示を信頼するのではなく、代わりにアクションを遅らせるようにしてください。
アクセシビリティと実稼働の慣習
ピッカーはネイティブの見た目を持つため、アクセシビリティのレビューから漏れがちですが、明確なラベル付けと予測可能な状態が必要です。
いくつかの慣習がすぐに効果を発揮します。
- アクセシビリティのラベルを追加する スクリーンリーダーでフィールドを理解できるようにする
- ラベルを明確にする 「国」は「選択」よりも良いです。
- 状態の復元をテストする フォームを再開し、前の選択されたアイテムが正しく表示されることを確認します。
- 選択に基づくロジックを取り巻くユニットテストを書きます: UI外側のロジックが最も重要であり、 Reactの動作をテストすることで、 状態の移行を保護することができます。
ピッカー自体はあまりビジネスクリティカルではありません。ピッカーの背後にある状態の変更が重要です。
動的フォームを安定させるには、この考え方が重要です。NativeBase ピッカーを入力面として扱い、実際のルールは状態、検証、送信フローに置きます。
結論
NativeBase ピッカーは、理解することで有用なものです。セットアップは簡単、スタイリングは実行可能、サーバーからドライブされたオプションリストは管理可能です。ただし、Android イベントハンドリングは重要なトラップです。フラッジなピッカーのコールバックからビジネスロジックを取り除き、状態駆動のエフェクトに移行すると、コンポーネントは予測可能になります。
古いコードベースでは、このワークアラウンドがよく機能します。重要なフローでは、 Select に移行することがよくありません。どちらの場合も、同じ鍵があります。ピッカーを信頼するのは、単にレンダリングされるだけではありません。
あなたのチームがCapacitorまたはElectronアプリを配信し、JavaScript、CSS、コピー、設定、資産の修正をストアのレビューを待たずに実行したい場合は、 Capgo Capgoをアップデートするためのプルリクエストを提出する価値があります。Capgoをアップデートするためのプルリクエストを提出することで、サインされたライブアップデート、ロールアウト制御、ロールバック保護、リリースの可視性を提供して、UIのバグのようなピッカーのリグレッションが生産環境に逃げ込まないようにすることができます。