ルートへのパラメータの受け渡し
「params
について話すときに詳しく説明します!」と言ったのを覚えていますか? さあ、その時が来ました。
いくつかのルートを持つスタックナビゲーターを作成し、それらのルート間を移動する方法がわかったので、ナビゲーション時にルートにデータを渡す方法を見てみましょう。
これには2つの要素があります
-
navigation.navigate
関数の2番目のパラメータとしてオブジェクトに配置することで、ルートにパラメータを渡します:navigation.navigate('RouteName', { /* パラメータはここに記述 */ })
-
画面コンポーネントでパラメータを読み取ります:
route.params
。
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
メソッドを使用できます。 navigate
で params
を渡してデータを返すことができます
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を介して画面にリンクすることも問題になります。理由は次のとおりです。
- URLは画面の表現であるため、パラメータ、つまり完全なユーザーオブジェクトも含める必要があります。これにより、URLが非常に長くなり、読みにくくなる可能性があります
- ユーザーオブジェクトはURLにあるため、存在しない、またはプロファイルに正しくないデータがあるユーザーを表すランダムなユーザーオブジェクトを渡すことができます
- ユーザーオブジェクトが渡されない場合、または形式が正しくない場合、画面はそれを処理する方法がわからないため、クラッシュが発生する可能性があります
より良い方法は、パラメータでユーザーのIDのみを渡すことです
navigation.navigate('Profile', { userId: 'jane' });
これで、渡された userId
を使用して、グローバルストアからユーザーを取得できます。 これにより、古いデータや問題のあるURLなどの多くの問題が解消されます。
パラメータに含めるべきものの例を次に示します
- ユーザーID、アイテムIDなどのID。例:
navigation.navigate('Profile', { userId: 'Jane' })
- アイテムのリストがある場合のデータの並べ替え、フィルタリングなどのパラメータ。例:
navigation.navigate('Feeds', { sortBy: 'latest' })
- ページネーションのタイムスタンプ、ページ番号、またはカーソル。例:
navigation.navigate('Chat', { beforeTime: 1603897152675 })
- 画面に入力して何かを作成するためのデータ。例:
navigation.navigate('ComposeTweet', { title: 'Hello world!' })
本質的に、パラメータで画面を識別するために必要な最小限のデータを渡します。多くの場合、これは単に完全なオブジェクトを渡す代わりにオブジェクトのIDを渡すことを意味します。 アプリケーションデータをナビゲーション状態から分離してください。
まとめ
navigate
とpush
は、移動先のルートにパラメータを渡すためのオプションの2番目の引数を受け入れます。 例:navigation.navigate('RouteName', { paramName: 'value' })
。- 画面内で
route.params
を介してパラメータを読み取ることができます navigation.setParams
を使用して画面のパラメータを更新できます- 初期パラメータは、
Screen
のinitialParams
propを介して渡すことができます - パラメータには、画面を表示するために必要な最小限のデータのみを含める必要があります。それ以上は含めないでください