Skip to content

Expo Routerでオブジェクトを渡す

Expo Routerを使用して画面間でオブジェクトを渡す際、画像URLを含む複雑なデータやネストされたオブジェクトを扱うと問題が発生します。URLパラメータには制限があり、以下のケースでうまく動作しません:

  • 画像URLのような特殊文字を含むデータ
  • 階層化されたオブジェクト構造
  • 日付など特定のデータ型
  • 大規模なデータオブジェクト

以下の実践的な解決策を解説します。


✅ 方法1:JSON文字列化でオブジェクトを渡す(シンプルな解決策)

データをJSON文字列に変換して渡す方法です。シンプルなデータ構造に適しています。

jsx
// 送信側
const getDetails = (item) => {
  router.push({ 
    pathname: `/details/${item.id}`, 
    params: { data: JSON.stringify(item) }
  });
};

// 受信側
export default function DetailsScreen() {
  const { data } = useLocalSearchParams();
  const item = JSON.parse(data || '{}');

  return <Text>{item.title}</Text>;
}

注意事項

  1. JSON.stringifyで長大な文字列を生成しないでください
  2. 機密データは含めないこと(URLに可視化されます)
  3. 型変換に注意(例: 日付は文字列に変換されます)

✅ 方法2:グローバル状態管理を使用(公式推奨)

React Navigation公式で推奨される方法です。React ContextZustandなどを活用します。

jsx
// Zustandストア例 (store.js)
import create from 'zustand'

const useItemStore = create((set) => ({
  currentItem: null,
  setCurrentItem: (item) => set({ currentItem: item }),
}));

// 送信側
const getDetails = (item) => {
  useItemStore.getState().setCurrentItem(item);
  router.push(`/details/${item.id}`);
};

// 受信側
export default function DetailsScreen() {
  const { id } = useLocalSearchParams();
  const item = useItemStore(state => state.currentItem);

  if (!item) return <Text>Loading...</Text>;
  return <Image source={{ uri: item.imageURL }} />;
}

メリット

  • URL長制限の影響なし
  • 複雑なオブジェクト・データ型を保持可能
  • ページリロード時も状態保持可能(永続化ライブラリと併用)

✅ 方法3:URLクエリパラメータで基本データを渡す

シンプルなプリミティブ値のみを渡す必要がある場合の手法です。

jsx
// 送信側
const getDetails = (item) => {
  router.push(`/details?id=${item.id}&title=${encodeURIComponent(item.title)}`);
};

// 受信側
export default function DetailsScreen() {
  const { id, title } = useLocalSearchParams();
  
  return <Text>ID: ${id}, Title: ${title}</Text>;
}

制限事項

  • 日本語などのマルチバイト文字にはencodeURIComponent必須
  • 画像URLなどの長い文字列には不向き
  • ネストした構造は表現不可能

状況別ベストプラクティス

ユースケース推奨方法理由
シンプルな小さなオブジェクトJSON文字列化実装が簡単
複雑なオブジェクトグローバル状態管理URL制限を回避可能
IDのみ渡し後方取得URLパラメータ最も標準的
機密データ扱う場合状態管理URLにデータが露出しない

💡 総合アドバイス
中規模以上のアプリケーションでは、状態管理を使用する方法が最もスケーラブルで安全です。Expo Routerは内部的にReact Navigationを使用しているため、公式ドキュメントでも状態管理を推奨しています。JSON文字列化はプロトタイプ開発時の応急処置に向いていますが、プロダクションコードでは依存しないようにしましょう。