UIが完成し、プロフィール画面に「写真をアップロード」ボタンがあり、ここからが簡単なはずの部分が急に簡単ではなくなる、という段階でしょう。実際の画像選択フローには、ネイティブの権限、OSが制御するインターフェース、多くの開発者が想定するのとは異なる戻り値の形、そして実際のビルドを出荷して初めて表面化するビルド時の細かな点が絡んできます。
そこで Expo Image Picker の出番です。デバイスのライブラリから画像や動画を選んだり、カメラで写真を撮ったりするためのシステムUIを開く、Expo公式ライブラリです。詳細は Expo パッケージリポジトリ を参照してください。実用面では、ネイティブのメディア入力への信頼できるブリッジが得られる一方で、すべてのデバイスで同じように動作するカスタムメディア体験が得られるわけではありません。
このガイドは、単なるデモ用ではなく、初めて実装する開発者のために書かれています。Managed workflow と Bare workflow のセットアップ、後で困らない権限管理、安全な結果のパース、そしてユーザーがファイルを選択した後の実践的なアップロードパターンなど、プロダクション環境で重要となる意思決定に焦点を当てています。カスタムネイティブ環境で開発している場合は、 Expo EAS update options について Capgo が代替ガイドで比較している内容との違いを理解するのにも役立ちます。.
目次
- Expo Image Picker の始め方
- インストールと基本設定
- カメラとメディアライブラリへのアクセス
- Picker の結果とオプションの処理
- 高度なパターンとプラットフォーム間の違い
- よくある問題のトラブルシューティング
Expo Image Picker の始め方
プロダクトマネージャーがプロフィール写真の機能を依頼します。1週間後、同じ機能にレシートアップロード、インシデントレポート用のカメラ撮影、初回に権限を拒否された場合のリトライも必要になります。ネイティブ権限、OS管理のUI、一時ファイル処理、バックエンドのアップロードフローに関わるため、画像入力の要件は急速に拡大します。
expo-image-picker ExpoのSDKモジュールがその役割を担います。プラットフォームのピッカーまたはカメラUIを開き、選択されたメディアをReact Nativeのcodeで処理できる形式で返します。JavaScriptのAPIは小さく、主な課題はマネージドプロジェクトとベアプロジェクトの両方で、ネイティブ設定、権限フロー、結果処理を正しく実装することです。
主なトレードオフはシンプルです。iOSとAndroidがそれぞれ独自のメディアUIを表示するようになり、カスタムピッカーを構築する必要がなくなります。通常、これはより良い結果をもたらします。ユーザーはシステム画面に慣れているため、権限プロンプトはOSが期待する通りに動作し、チームはJavaScriptでギャラリー実装をメンテナンスする必要がなくなります。
これはReactインターフェースを持つネイティブ統合機能として扱ってください。
この考え方が役立つのは、失敗の原因がピッカーを呼び出すボタンにあることは稀だからです。通常、以下の3つのいずれかから生じます:
- ネイティブ設定: プラグイン設定の欠落、権限文字列の誤り、設定変更後の古いビルド
- ランタイム動作: ユーザーがアクセスを拒否したり、iOSでライブラリへの限定アクセスを許可したり、何も選択せずにフローをキャンセルしたりする場合
- 結果の解析: 現在の API は
assets配列を返すため、result.uri直接読み取る古い例は失敗します
ワークフローの選択によってセットアップの流れも変わります。マネージド Expo アプリでは、ネイティブ側の作業の多くは app config にあり、その設定が変わると再ビルドが必要です。Bare アプリでも Expo モジュール API は利用できますが、iOS と Android のプロジェクト設定をより直接的に確認する必要があります。Expo Go ではなくカスタムクライアントを使うチームには、このガイドは Capgo の内容と組み合わせるのがおすすめです Expo EAS の代替手段 Expo Goの枠を超えて、ネイティブモジュールのテストが必要なチーム向け。
この違いは、本ガイドの後半において非常に重要です。なぜなら、理想的な動作(ハッピーパス)だけでは不十分だからです。優れたPickerの実装とは、両方のワークフローで動作し、ユーザーを混乱させることなくプラットフォーム固有の権限設定を処理し、ローカルのプレビューで止まるのではなく、アップロード層へ利用可能なファイルを渡せるものを指します。
インストールと基本設定
インストールはコマンド一つで完了します。しかし、実機やカスタムDev Client、そして本番ビルドでPickerが正しく動作するかどうかは、ネイティブ設定を適切に行えるかにかかっています。
expo-image-picker 写真、動画、カメラキャプチャ用のプラットフォーム固有のPickerに対して、Reactから扱える API を提供します。JavaScriptからの呼び出しは簡単ですが、セットアップは一筋縄ではいきません。なぜなら、写真やカメラへのアクセス権限はReact Nativeではなく、iOSやAndroidによって制御されているからです。

まずは、Expoのバージョン対応インストーラーから開始します:
npx expo install expo-image-picker
使用する expo install の代わりに npm install または yarn add. Expoはパッケージのバージョンを SDK と一致させるため、ネイティブの互換性に関するよくある問題を回避できます。Expoモジュールがリリースプロセスにどのように適合するかを検討している場合、これは Expoツール概要 は役立つリファレンスです。
Managed workflow のセットアップ
Managed workflow では、ビルド時に Expo がネイティブの変更を適用できるよう、app config でプラグインを宣言します。
〜を使った例 app.json:
{
"expo": {
"plugins": ["expo-image-picker"]
}
}
これは最小限のセットアップです。実際には、特に iOS ではシステムプロンプトでアプリのアクセス理由を説明する必要があるため、権限テキストも追加するのが一般的です。文言はユーザーのアクションに合わせて具体的にしましょう。「メディアへのアクセスが必要です」よりも「プロフィール写真をアップロードします」の方が適切です。
運用上の細かい点が、多くの時間を無駄にします。設定の変更 plugins、権限文字列、その他のネイティブ設定には再ビルドが必要です。JavaScript のリロードではこれらの変更は適用されません。Expo Go では、クライアントに既に含まれている機能に制限されます。development build や production build では、新しいビルドを行って初めてネイティブプロジェクトに設定が反映されます。
Bare React Native のセットアップ詳細
Bare アプリでもパッケージ API は同じですが、ネイティブプロジェクトをより詳細に自身で確認する必要があります。まず確認すべきは iOS の usage descriptions です。ライブラリを開く、カメラを起動する、あるいは音声付きでビデオを録画するフローがある場合、アプリには対応する権限文字列が Info.plist 再ビルドする前に必要です。
Bare プロジェクト向けの実践的なチェックリストは次のとおりです:
- インストール
expo-image-pickerを使用してnpx expo install expo-image-picker. - プロジェクトで Expo の config plugin を使っている場合は、プラグイン設定を追加します。
- iOS の使用目的の説明が、提供している機能と一致していることを確認します。
- ネイティブ設定を変更したら、iOS と Android のアプリを再ビルドします。
パーミッションの説明文が不足していると、UI code は正常でボタンハンドラーも動くため、ランタイムバグのように見えがちです。原因はスタックの下層にあります。私は通常、次を確認します: Info.plistアプリ設定、そしてコンポーネント code に触る前に、現在のビルドに最新のネイティブ変更が含まれているかどうか。
いくつかの習慣で、セットアップはもっと予測しやすくなります:
- 実際のアクションに合わせて権限の説明文を書く: ユーザーがなぜプロンプトが表示されるのか理解できるようにする。
- カメラとライブラリを個別に設定する: 片方が動作しても、もう片方が失敗することがある。
- ネイティブの変更後は再ビルドする: ホットリロードやFast Refreshではネイティブ権限は更新されない。
- 実機でテストする: シミュレータの挙動は、権限やカメラの問題を隠すことがある。
開発中はピッカーが動作するのに、TestFlightやPlay Storeのビルドで壊れる場合は、まず設定の問題として扱うべきだ。多くの場合、実際に設定の問題だ。
カメラとメディアライブラリへのアクセス
ユーザーが「写真をアップロード」をタップし、カメラやライブラリが開くことを期待している。その瞬間、アプリのやることは1つだ。正しいシステムUIを開き、拒否やキャンセルで画面が壊れないように処理し、プレビューやアップロードに使えるローカルファイル参照を返すことだ。
iOSとAndroidの両方で、managed buildとbare buildをテストするまで、それは簡単に思える。JavaScriptのAPIはコンパクトだが、ランタイムの挙動は依然としてOSのプロンプト、デバイスのハードウェア、そして以前に設定したネイティブ権限に依存している。

最小構成で安全なコンポーネント
Expoのmanagedワークフローとbareワークフローの両方で、コアのフローは同じです。必要な権限をリクエストし、ピッカーを起動し、ユーザーがキャンセルしたかどうかを確認し、次にから最初のアセットを読み取ります。 result.assets.
ベースラインのコンポーネントは次のようになります。
import { useState } from 'react';
import { View, Button, Image, Alert } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
export default function PhotoInput() {
const [imageUri, setImageUri] = useState<string | null>(null);
const pickFromLibrary = async () => {
const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permission.granted) {
Alert.alert('Permission required', 'Please allow photo library access.');
return;
}
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 1,
});
if (result.canceled) return;
const asset = result.assets?.[0];
if (!asset?.uri) return;
setImageUri(asset.uri);
};
const takePhoto = async () => {
const permission = await ImagePicker.requestCameraPermissionsAsync();
if (!permission.granted) {
Alert.alert('Permission required', 'Please allow camera access.');
return;
}
const result = await ImagePicker.launchCameraAsync({
allowsEditing: true,
quality: 1,
});
if (result.canceled) return;
const asset = result.assets?.[0];
if (!asset?.uri) return;
setImageUri(asset.uri);
};
return (
<View>
<Button title="Choose from library" onPress={pickFromLibrary} />
<Button title="Take photo" onPress={takePhoto} />
{imageUri ? (
<Image
source={{ uri: imageUri }}
style={{ width: 200, height: 200 }}
/>
) : null}
</View>
);
}
ここでは3つの詳細が重要です。
- ライブラリ権限とカメラ権限は別々にリクエストしてください。それぞれ独立して失敗します。
- キャンセルはエラー状態ではなく、通常のユーザー操作として扱ってください。
- 読み込み元:
assets[0]。ピッカーはトップレベルのではなく、アセットの配列を返すためです。uri.
ライブラリとカメラのフロー
動作する機能を最速で実装したい場合は、ライブラリフローから始めるのがおすすめです。テストが容易で、シミュレータ環境での動作範囲が広く、カメラハードウェアのエッジケースを回避できます。結果処理のパスが安定してからカメラ対応を追加してください。
開発環境では、カメラパスの失敗要因がより多くなります。iOSシミュレータのサポートは限定的です。Androidエミュレータでは、実機と一致するカメラ動作が公開されない場合があります。bareプロジェクトでは、これらのギャップにより、実際の問題がネイティブ設定やテスト環境にあるにもかかわらず、コンポーネントcodeを調べることになる可能性があります。
クリーンなUIパターンとして、ピッカーを呼び出す前にユーザーにソースを確認させる方法です API:
const showPickerOptions = () => {
Alert.alert('Upload image', 'Choose a source', [
{ text: 'Camera', onPress: takePhoto },
{ text: 'Photo Library', onPress: pickFromLibrary },
{ text: 'Cancel', style: 'cancel' },
]);
};
この分離により、各関数の役割が明確になります。また、後でアナリティクス、フィーチャーフラグ、またはバックエンド固有のルールを追加しやすくなります。例えば、プロフィール画像にはライブラリからのアップロードを許可し、本人確認にはカメラでの新規撮影を必須とするチームもあります。
アプリ全体でExpo以外のファイルアクセスパターンをサポートしている場合、またはネイティブスタック間で規約を比較している場合は、 Capacitor のフォトライブラリリファレンス が有用なコンテキストになります。
チームメンバーやQAにこのフローを見せる際は、短いデモがあると便利です:
システムUIの挙動について
expo-image-picker プラットフォームのピッカーやカメラUIが開きます。このフロー内のすべての画面をアプリ側で制御できるわけではありません。この違いは重要です。「自分のデバイスでは動いた」という言葉は、多くの場合「テストしたパスがOSに許可された」という意味に過ぎないからです。
iOSでは、ユーザーがフルアクセスではなくライブラリへの限定的なアクセスを許可する場合があります。Androidでは、OSのバージョンやベンダー独自のUIによってピッカーの挙動が変わることがあります。Managed Workflowのプロジェクトでは、Expoがネイティブ側の連携処理をより多く担います。Bare Workflowのプロジェクトでは、ビルドしたアプリに自分で加えたネイティブ権限の変更が含まれているか確認する必要があります。JavaScriptの呼び出し箇所は同じでも、実行時の結果は異なることがあります。
私は通常、機能を「完了」とする前に、以下のケースをテストします:
- 初回権限リクエスト
- 権限の拒否
- ユーザーによるキャンセル
- ライブラリからの選択成功
- 実機でのカメラ撮影成功
- 返されたローカルURIの即時プレビュー
これらのケースは、実際の本番環境の挙動に直結します。また、ファイルをサーバー、モデレーション用のpipeline、または以下のようなpublish先のエンドポイントに送る必要がある場合、次のステップへスムーズに移行できます。 Instagram へのメディア投稿 API.
Picker の結果とオプションの処理
ピッカーの結果は、本番環境で本格的なロジックが必要な部分です。システムUIは単なるファイルパスではなく構造化オブジェクトを返すため、ここでの小さなミスがプレビューの破損、アップロードの失敗、またはユーザーがキャンセルした後のクラッシュにつながります。
resultオブジェクトの正しい読み取り方
現在のExpoアプリで重要になる結果の形状は result.assets[0].uriであり、トップレベルの result.uriではありません。この詳細は、ネイティブのセットアップが異なるものの、JavaScriptのAPIが同じであるため、managedワークフローとbareワークフローの両方のプロジェクトに影響します。
ガードファーストパターンを使用します:
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 1,
});
if (result.canceled) {
return;
}
const asset = result.assets?.[0];
if (!asset) {
return;
}
const { uri } = asset;
setImageUri(uri);
これは私が最も頻繁に見る2つの失敗ケースを処理します。キャンセルされたピッカーからは読み取れるアセットが得られず、code が result.assets[0] 常に存在すると仮定すると、実行時に失敗します。
URIを取得できたら、プレビューのレンダリングは簡単です:
<Image source={{ uri: imageUri }} style={{ width: 240, height: 240 }} />
後でアップロードする予定がある場合は、URIだけでなく、 asset オブジェクト全体を保持してください。実際には、 fileName, mimeType, width, heightや fileSize は検証、ログ出力、またはよりクリーンなマルチパートリクエストの構築に役立つことが多いです。
後続の挙動に影響するオプション
いくつかのピッカーオプションは、選択画面だけでなく、ファイルサイズ、編集動作、バックエンドが受け入れるべき内容にも影響を与えます。
| オプション | 種類 | 変更内容 | 一般的な用途 |
|---|---|---|---|
mediaTypes |
配列 | ユーザーの選択範囲を制限 | API が画像のみを受け付ける場合は、選択を画像に限定します |
allowsEditing |
boolean | 対応しているOSで、切り抜きや編集UIを表示します | アバター、正方形のカバー画像、レシート撮影 |
quality |
number | 対応している画像出力を圧縮します | モバイル回線でのアップロードサイズを削減します |
base64 |
boolean | 結果にエンコードされた画像データを追加します | インライン画像データを明示的に必要とする連携専用です |
見落としがちなトレードオフがいくつかあります:
allowsEditing画像の枠が固定の形状やサイズの場合に有効です。サーバー側で独自の切り抜きパイプラインを実行していて、元のファイルが必要な場合にはあまり適していません。qualityアップロード時間、メモリ負荷、サーバーストレージに影響します。quality: 1が自動的に正しい選択になるわけではありません。mediaTypesはバックエンドのルールと一致している必要があります。サーバーが動画を拒否する場合は、ピッカーから返さないようにしてください。base64はメモリ内のペイロードサイズを増やします。受信サービスが必要としない限り、避けてください。
最後の点は、メモリの少ないデバイスでは重要です。プレビューやマルチパートアップロードの受け渡しには、通常はローカルファイルURIの方が適しています。Base64にも有効な用途はありますが、ファイル参照を渡す場合に比べてコストが高くなります。
URIとbase64の違い
ほとんどのアプリでは、ルールはシンプルです:
- 使用する URI プレビュー用。
- 使用する URI ファイルアップロード用。
- 使用する base64 受信側システムがエンコードされたコンテンツを明示的に要求した場合のみ使用します。
このパターンなら、picker の code を小さく保ち、テストもしやすくなります。また、最終的に外部プラットフォームへ公開するサービスも含め、多くのバックエンドメディアフローの構築方法とも一致します。たとえば次のような Instagram へのメディア投稿 API.
チームが頻繁に OTA アップデートを配信したり、画像中心のアセットをアプリ配信経由で送ったりする場合、ここでのファイルサイズの決定はパイプライン全体に影響します。こちらの アプリアップデート向けの画像最適化ガイド は、picker の設定における有用な補足資料となります。
実際のアプリ向けのより安全なresultパターン
デモ用の code であれば、 imageUri のみを保存する形でも問題ありません。本番環境では、正規化されたオブジェクトを保存してください。そうすることで、プレビュー、バリデーション、アップロード、リトライといった次のステップで、毎回 picker の生のレスポンスを再解釈する必要がなくなります。
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing: true,
quality: 0.8,
});
if (result.canceled || !result.assets?.length) {
return;
}
const asset = result.assets[0];
setSelectedImage({
uri: asset.uri,
fileName: asset.fileName ?? 'upload.jpg',
mimeType: asset.mimeType ?? 'image/jpeg',
width: asset.width,
height: asset.height,
fileSize: asset.fileSize ?? null,
});
これにより、アプリ内でのデータ構造が予測可能になります。また、他の部分でネイティブの違いを調整している間も、アプリの code が安定するため、managed プロジェクトと bare プロジェクトの同期も容易になります。
最後に確認しておくと安心です。「念のため」という理由で余計な result フィールドを有効にしないでください。必要なデータだけをリクエストし、ピッカーはファイル処理のステップではなく、選択に特化したものとして保ちましょう。
高度なパターンとプラットフォーム間の違い
ピッカー機能は、最初の選択画像がリトライ、認証ヘッダー、ネイティブ権限の違い、実際のアップロードエンドポイントを生き延びなければならない瞬間に、シンプルさを失います。 expo-image-picker 選択処理はうまく処理されます。機能の残りはあなたのアプリ次第です。

実践的なuploadパターン
ファイルアップロードを期待する API に対しては、 FormData 依然として最も安全なデフォルトです。Rails、Node、Laravel、Django、Go などの一般的なバックエンドで動作し、ピッカーをトランスポートの関心事から分離できます。
async function uploadImage(imageUri: string) {
const formData = new FormData();
formData.append('file', {
uri: imageUri,
name: 'upload.jpg',
type: 'image/jpeg',
} as any);
const response = await fetch('https://your-api.example.com/uploads', {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
},
});
if (!response.ok) {
throw new Error('Upload failed');
}
return response.json();
}
その code だけで経路が機能することは証明できますが、本番アプリでは通常もう1層必要です。可能な場合は選択したアセットから name と type 情報を派生させ、認証はピッカー関数の外側で行い、アップロード状態はピッカーの状態と分けて管理してください。そうすれば、リクエストが失敗してもユーザーがライブラリを開き直す必要はありません。
レビューでよく見る失敗を防ぐには、次のチェックが有効です:
- ローカルの
uriが存在することをリクエスト構築前に確認する - アップロード前にプレビューを表示し、誤ったファイルに早く気づけるようにする
- リクエスト処理中は連打を防ぐ
- ネットワーク障害は、ピッカーのキャンセルや権限エラーと分けて処理する
- バックエンドのバリデーションで、大きすぎるファイル、未対応のMIMEタイプ、認証情報の欠落が拒否されることを想定しておく
バックエンドがmultipartではなくbase64を必要とする場合、それは通常サーバー側の制約であり、ピッカーの要件ではありません。モバイルではmultipartの方がメモリ効率がよく、挙動も理解しやすいです。
プラットフォーム間の違いが重要になる場面
ピッカーのUIはネイティブなので、ネイティブの挙動を継承します。これはユーザーが見る内容と、code が前提とすべき内容の両方に影響します。
iOSでは、編集フローや権限プロンプトがAppleの慣習に従います。限定された写真アクセスでは、完全な権限が与えられたデバイスでテストアカウントが見たものよりも、返されるアセットのセットが狭くなることがあります。Androidでは、OSバージョンやメーカーのスキンによってピッカーの挙動がより大きく異なり、特にアルバム、ファイル名、カメラキャプチャの返却方法がそうです。Bare React Nativeアプリはネイティブセットアップをより多く所有するため、これらの違いをより直接的に感じますが、マネージドExpoアプリでも、ピッカーを完全に均一なものではなく、プラットフォームに依存するものとして扱うcode が必要です。
実用的なルールはシンプルです。デバイス間でUIやメタデータが同一であることに依存するのではなく、検証できるフィールドに依存してください。
実際のアプリでは、いくつかの例が重要です:
- 編集とクロップ: UIとクロップの挙動は、iOSとAndroidで同一ではありません
- 返されるメタデータ:
fileName,mimeTypeやfileSize欠落したり一貫性がなかったりするため、フォールバックを追加してください - 権限: iOSの写真アクセスは選択されたアイテムに限定されることがありますが、Androidの挙動はOSバージョンやシステムピッカーのサポートにより大きく依存します
- カメラ出力: 撮影した画像は、ライブラリのアセットとは異なるファイル名、向き、圧縮特性で返されることがあります
チームがExpo以外でも開発している場合、この DesignStackアプリ開発ガイド は、単一のライブラリの範囲を超えて発生するメディア処理の判断に役立つAndroidの背景情報を提供します。
Managedとbareワークフローの違い
この段階になると、セットアップの選択が運用面に影響し始めます。
Managed workflowでは、権限文字列やプラグイン設定は通常app configに記述され、ネイティブの変更は新しいbuildを作成するときに適用されます。これでJavaScript側のコードはクリーンに保てますが、設定の修正が次のネイティブbuildまで反映されないということでもあります。OTAアップデートで不足しているネイティブ権限を補うことはできません。
Bare workflowでは、同じ機能でも管理すべき要素が増えます。iOSのUsage Description、Android Manifestの挙動、パッケージのインストール、リビルドのタイミングを自分で確認する必要があります。利点はコントロールできること。代償は、Pickerの問題がJavaScriptの呼び出し側ではなくネイティブ設定に起因する可能性があることです。
ExpoとCapacitorを行き来するチームは、これらの抽象化レイヤーがどれほど違うかを過小評価しがちです。Capgoには分かりやすい解説があります。 Capacitorがプラットフォーム間の違いをどう処理するかチームがネイティブセットアップをどこまで自分たちで担うか決めるときの、良い比較材料になります。
どちらのworkflowでも私の考えは一貫しています。Pickerのcodeは狭く保ち、結果は一度正規化し、専用のAPIレイヤー経由でアップロードする。プラットフォーム固有の挙動は、思い込みでごまかさず、明示的に設定してテストすべきものとして扱います。
よくある問題のトラブルシューティング
Expo Image Pickerのバグの多くは、少数のカテゴリに収まります。最速の解決策は通常、config、権限、結果の処理、レンダリングのどのレイヤーで失敗しているかを見極めることです。

よくある失敗のクイックチェック
ピッカーが開かない、または権限の処理が失敗する場合は、まずネイティブのセットアップを確認してください。特に bare アプリでは、iOS の usage description の不足がよくある根本原因です。
ユーザーがピッカーを閉じた後にアプリがクラッシュする場合は、結果のハンドリングを確認してください。多くの実装では、直接 URI が返される前提のまま、次の canceled チェックを飛ばしています。
いくつかの簡単なマッピングが役立ちます:
- Permission denied エラー: アプリの設定とネイティブの権限文字列を確認してから、再ビルドしてください。
undefinedimage URI: 読み込み元:result.assets?.[0]?.uriではなく、result.uri.- キャンセル後に何も起きない: それは正しい挙動かもしれません。キャンセルは no-op 状態として扱ってください。
- 画像がレンダリングされない: URI が state に保存され、以下に渡されているか確認してください:
<Image source={{ uri }} />. - シミュレーターでカメラの挙動がおかしい: ライブラリのバグを疑う前に、実機でテストしてください。
本番環境向けの短いチェックリスト
リリース前の最終チェックとして使用してください:
- Expo ツールでインストール: 使用する
npx expo install expo-image-picker. - ネイティブ部分の設定: プラグインと必要な権限の説明を追加します。
- 意図的に権限を要求します: カメラとメディアライブラリのフローを分離します。
- すべての結果をガードします: 確認
result.canceledそして安全に読み取りますassets[0]. - URIベースのアップロードを優先します: base64は特殊なケースにのみ使用します。
- 実機でテストします: 特にカメラ撮影と権限プロンプトについて。
チームが React Native プロジェクトと並行して Capacitor や Electron アプリをリリースする場合、 Capgo 変更のたびにストアレビューを待たずに、JavaScript、CSS、設定、アセットのアップデートを配信できる一つの選択肢です。アップロードUI、バリデーションルール、文言、ピッカーフロー周辺のアセット処理など、画像関連の修正がWebレイヤーにある場合に関係します。