画面間の移動
前のセクション、「React Navigation入門」では、2つのルート(Home
とDetails
)を持つスタックナビゲータを定義しましたが、ユーザーがHome
からDetails
に移動する方法については説明しませんでした(コード内で初期ルートを変更する方法については説明しましたが、ユーザーに別の画面を表示するためにリポジトリをクローンしてコード内のルートを変更させることは、想像できる最悪のユーザーエクスペリエンスの1つです)。
これがウェブブラウザであれば、次のような記述ができます。
<a href="details.html">Go to Details</a>
別の書き方としては、次のようなものがあります。
<a
onClick={() => {
window.location.href = 'details.html';
}}
>
Go to Details
</a>
後者と同様の方法を使用しますが、window.location
グローバル変数を使用する代わりに、画面コンポーネントに渡されるnavigation
プロップを使用します。
新しい画面への移動
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
// ... other code from the previous section
これを詳しく見ていきましょう
navigation
-navigation
プロップは、ネイティブスタックナビゲータ内のすべての画面コンポーネント(定義)に渡されます(これについては後ほど「navigationプロップの詳細」で詳しく説明します)。navigate('Details')
- ユーザーを移動させたいルートの名前を指定して、navigate
関数(navigation
プロップ上にある - 名前付けは難しい!)を呼び出します。
ナビゲータで定義していないルート名でnavigation.navigate
を呼び出すと、開発ビルドではエラーが、本番ビルドでは何も起こりません。言い換えれば、ナビゲータで定義されているルートにのみ移動できます。任意のコンポーネントに移動することはできません。
したがって、現在2つのルートを持つスタックがあります。1) Home
ルート 2) Details
ルート。Details
画面からもう一度Details
ルートに移動するとどうなるでしょうか?
ルートへの複数回移動
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
このコードを実行すると、「もう一度Detailsへ移動」をタップしても何も起こらないことに気付くでしょう!これは、すでにDetailsルートにいるためです。navigate
関数は、おおよそ「この画面に移動する」という意味であり、すでにその画面にいる場合は、何も起こらないのは理にかなっています。
実際に別の詳細画面を追加したいとしましょう。これは、各ルートに一意のデータを渡す場合によくあります(これについては、後でparams
について説明する際に詳しく説明します)。これを行うには、navigate
をpush
に変更できます。これにより、既存のナビゲーション履歴に関係なく、新しいルートを追加するという意図を表現できます。
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
push
を呼び出すたびに、新しいルートがナビゲーションスタックに追加されます。navigate
を呼び出すと、まずその名前の既存のルートを探し、スタックにまだ存在しない場合にのみ新しいルートをプッシュします。
戻る
ネイティブスタックナビゲータによって提供されるヘッダーには、アクティブな画面から戻る操作が可能である場合(ナビゲーションスタックに画面が1つしかない場合、戻る操作はできないため、戻るボタンはありません)、自動的に戻るボタンが含まれます。
プログラムでこの動作をトリガーしたい場合があり、その場合はnavigation.goBack();
を使用できます。
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
Androidでは、React Navigationはハードウェアの戻るボタンにフックし、ユーザーが押すとgoBack()
関数を自動的に実行するため、ユーザーの期待どおりに動作します。
もう1つの一般的な要件は、複数画面に戻る操作です。たとえば、スタックで複数の画面深くに入り込み、それらすべてを閉じてもう最初の画面に戻りたい場合です。この場合、Home
に戻りたいことがわかっているので、navigate('Home')
(push
ではありません!試して違いを確認してください)を使用できます。別の方法としては、スタック内の最初の画面に戻るnavigation.popToTop()
があります。
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
<Button
title="Go back to first screen in stack"
onPress={() => navigation.popToTop()}
/>
</View>
);
}
まとめ
navigation.navigate('RouteName')
は、スタックにまだない場合、新しいルートをネイティブスタックナビゲータにプッシュします。そうでない場合は、その画面にジャンプします。navigation.push('RouteName')
は何度でも呼び出すことができ、ルートをプッシュし続けます。- ヘッダーバーには自動的に戻るボタンが表示されますが、
navigation.goBack()
を呼び出すことでプログラムで戻る操作を行うことができます。Androidでは、ハードウェアの戻るボタンは期待どおりに動作します。 navigation.navigate('RouteName')
を使用してスタック内の既存の画面に戻ることも、navigation.popToTop()
を使用してスタック内の最初の画面に戻ることもできます。navigation
プロップは、すべての画面コンポーネント(ルート構成で画面として定義され、React Navigationによってルートとしてレンダリングされるコンポーネント)で使用できます。