メインコンテンツにスキップ
バージョン: 6.x

ルートへのパラメータの受け渡し

params について話すときに詳しく説明します!」と言ったのを覚えていますか? さあ、その時が来ました。

いくつかのルートを持つスタックナビゲーターを作成し、それらのルート間を移動する方法がわかったので、ナビゲーション時にルートにデータを渡す方法を見てみましょう。

これには2つの要素があります

  1. navigation.navigate 関数の2番目のパラメータとしてオブジェクトに配置することで、ルートにパラメータを渡します: navigation.navigate('RouteName', { /* パラメータはここに記述 */ })

  2. 画面コンポーネントでパラメータを読み取ります: route.params

注記

渡すパラメータはJSONシリアライズ可能であることをお勧めします。そうすることで、状態の永続化を使用できるようになり、画面コンポーネントはディープリンクを実装するための適切なコントラクトを持つようになります。

function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}

function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId, otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() =>
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}

初期パラメータ

画面に初期パラメータを渡すことができます。この画面に移動するときにパラメータを指定しなかった場合、初期パラメータが使用されます。 また、渡すパラメータとも浅くマージされます。 初期パラメータはinitialParams propで指定できます

<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>

パラメータの更新

画面は、状態を更新できるように、パラメータも更新できます。 navigation.setParams メソッドを使用すると、画面のパラメータを更新できます。 詳細については、setParams のAPIリファレンスを参照してください。

基本的な使い方

navigation.setParams({
query: 'someText',
});
注記

title などの画面オプションを更新するために setParams を使用しないでください。 オプションを更新する必要がある場合は、代わりに setOptions を使用してください。

前の画面にパラメータを渡す

パラメータは、新しい画面にデータを渡すためだけでなく、前の画面にデータを渡すためにも役立ちます。 たとえば、投稿作成ボタンのある画面があり、投稿作成ボタンが新しい画面を開いて投稿を作成するとします。 投稿を作成した後、投稿のデータを前の画面に渡したいとします。

これを達成するには、画面が既に存在する場合に goBack のように動作する navigate メソッドを使用できます。 navigateparams を渡してデータを返すことができます

function HomeScreen({ navigation, route }) {
React.useEffect(() => {
if (route.params?.post) {
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);

return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Create post"
onPress={() => navigation.navigate('CreatePost')}
/>
<Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
</View>
);
}

function CreatePostScreen({ navigation, route }) {
const [postText, setPostText] = React.useState('');

return (
<>
<TextInput
multiline
placeholder="What's on your mind?"
style={{ height: 200, padding: 10, backgroundColor: 'white' }}
value={postText}
onChangeText={setPostText}
/>
<Button
title="Done"
onPress={() => {
// Pass and merge params back to home screen
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
}}
/>
</>
);
}

ここで、「完了」を押すと、ホーム画面の route.params が更新され、navigate で渡した投稿テキストが反映されます。

ネストされたナビゲーターにパラメータを渡す

ネストされたナビゲーターがある場合は、パラメータを少し異なる方法で渡す必要があります。 たとえば、Account 画面内にナビゲーターがあり、そのナビゲーター内の Settings 画面にパラメータを渡したいとします。 その後、次のようにパラメータを渡すことができます

navigation.navigate('Account', {
screen: 'Settings',
params: { user: 'jane' },
});

ネストの詳細については、ナビゲーターのネストを参照してください。

パラメータに含めるべきもの

どのような種類のデータをパラメータに含めるべきかを理解することが重要です。 パラメータは画面のオプションのようなものです。 画面に表示される内容を設定するための情報のみを含める必要があります。 画面自体に表示されるデータ全体を渡すのは避けてください(例:ユーザーオブジェクトではなくユーザーIDを渡す)。 また、複数の画面で使用されるデータを渡すのも避けてください。そのようなデータはグローバルストアに配置する必要があります。

ルートオブジェクトをURLのように考えることもできます。 画面にURLがあった場合、URLには何が含まれている必要がありますか? パラメータには、URLに含めるべきでないと考えるデータを含めるべきではありません。 これは多くの場合、画面が何であるかを決定するために必要なデータをできるだけ少なくしておく必要があることを意味します。 ショッピングWebサイトにアクセスすることを考えてみてください。製品リストが表示されている場合、URLには通常、カテゴリ名、並べ替えの種類、フィルターなどが含まれていますが、画面に表示される実際の製品リストは含まれていません。

たとえば、Profile 画面があるとします。 移動するときに、パラメータでユーザーオブジェクトを渡したくなるかもしれません

// Don't do this
navigation.navigate('Profile', {
user: {
id: 'jane',
firstName: 'Jane',
lastName: 'Done',
age: 25,
},
});

これは便利に見え、追加の作業なしで route.params.user を使用してユーザーオブジェクトにアクセスできます。

ただし、これはアンチパターンです。 ユーザーオブジェクトなどのデータは、ナビゲーション状態ではなくグローバルストアに配置する必要があります。 そうしないと、同じデータが複数の場所に複製されます。 これは、ナビゲーション後にユーザーオブジェクトが変更された場合でも、プロファイル画面に古いデータが表示されるなどのバグにつながる可能性があります。

また、ディープリンクまたはWebを介して画面にリンクすることも問題になります。理由は次のとおりです。

  1. URLは画面の表現であるため、パラメータ、つまり完全なユーザーオブジェクトも含める必要があります。これにより、URLが非常に長くなり、読みにくくなる可能性があります
  2. ユーザーオブジェクトはURLにあるため、存在しない、またはプロファイルに正しくないデータがあるユーザーを表すランダムなユーザーオブジェクトを渡すことができます
  3. ユーザーオブジェクトが渡されない場合、または形式が正しくない場合、画面はそれを処理する方法がわからないため、クラッシュが発生する可能性があります

より良い方法は、パラメータでユーザーのIDのみを渡すことです

navigation.navigate('Profile', { userId: 'jane' });

これで、渡された userId を使用して、グローバルストアからユーザーを取得できます。 これにより、古いデータや問題のあるURLなどの多くの問題が解消されます。

パラメータに含めるべきものの例を次に示します

  1. ユーザーID、アイテムIDなどのID。例:navigation.navigate('Profile', { userId: 'Jane' })
  2. アイテムのリストがある場合のデータの並べ替え、フィルタリングなどのパラメータ。例:navigation.navigate('Feeds', { sortBy: 'latest' })
  3. ページネーションのタイムスタンプ、ページ番号、またはカーソル。例:navigation.navigate('Chat', { beforeTime: 1603897152675 })
  4. 画面に入力して何かを作成するためのデータ。例:navigation.navigate('ComposeTweet', { title: 'Hello world!' })

本質的に、パラメータで画面を識別するために必要な最小限のデータを渡します。多くの場合、これは単に完全なオブジェクトを渡す代わりにオブジェクトのIDを渡すことを意味します。 アプリケーションデータをナビゲーション状態から分離してください。

まとめ

  • navigatepush は、移動先のルートにパラメータを渡すためのオプションの2番目の引数を受け入れます。 例:navigation.navigate('RouteName', { paramName: 'value' })
  • 画面内で route.params を介してパラメータを読み取ることができます
  • navigation.setParams を使用して画面のパラメータを更新できます
  • 初期パラメータは、ScreeninitialParams propを介して渡すことができます
  • パラメータには、画面を表示するために必要な最小限のデータのみを含める必要があります。それ以上は含めないでください