##はじめに
つい最近GraphQLやApollo、ReactNativeを触り始めた初学者です。違う点などあればコメントいただけると嬉しいです!
インターンの業務でnavigation.navigate()
とnavigation.push()
は同じ画面遷移に見えるけど何が違うんだ!?と思ったので自分なりにまとめてみます。
##navigateとpushの違いを知って、実装するときに役立てたい
まずはお馴染み(?)の公式ドキュメントで確認してみると、、
navigation
- navigate - go to another screen, figures out the action it needs to take to do it
- push - push a new route onto the stack
と言っていますね。この通りの解釈だとnavigate
は単なる別の画面への遷移、push
はstack上に新しいrouteが作られるようです。
###routeってなんぞや...
単語の意味の通り、経路みたいなものだと思っています。
以下のコードを見てください。
// In App.js in a new project
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
このname="Home"
,name="Details"
がroute nameです。(このroute nameは地点名という印象を持つとわかりやすいかなと思います)stack navigatorを作ることで、HomeとDetailsという地点を結ぶ経路ができているイメージです。
###navigateとpushの違い
とてもわかりやすく書かれているなと思ったのが公式のこの部分。
https://reactnavigation.org/docs/navigating/
簡潔に言うと、navigateはすでに存在する画面(route)を行き来し、一方でpushは新しくstack上に画面遷移のrouteを作ると言う点で異なります。
上のコードでHomeScreenにいる状態からDetailsに遷移してみます。この時は上で述べたようにすでにHomeとDetailsを結ぶrouteができているのでnavigation.navigate
を使用します。
Home Componentを以下のように修正してボタンを押すことでDetailsに飛んでみましょう。
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>
);
}
では次にあまり見かけませんがDetailsからDetailsに飛んでみましょう。Detailsを以下のように修正してみます。この時はnavigation.push
を使用します。なぜかというと、HomeとDetails間のrouteはすでに存在していますが、DetailsとDetails間のrouteはまだ作成されていないからです。仮にnavigation.navigate
を使用しても画面は遷移されません。
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>
);
}
###navigation.navigateを使う場面でnavigation.pushを使ってしまうとどうなるのか
単純に画面に遷移するはずが新しく経路を作ってしまいます。
ここからは私個人がこんな問題が起きるんじゃないかな?と予想していることなのですが...
経路を作るたびすなわちnavigation.push
を使うたびにheaderには自動的に一つ前の画面に戻ることができるnabigation.goBack()
という機能が提供されます。
push()
したときにこのgoBack()
を使うとpush()
を実行した一つ前の画面に戻ります。上の例では画面が二つしかないのでわかりにくいのですが、画面の数がもっと増えてくると画面を操作して遷移しているうちに意図した画面に戻れなくなる可能性があるのかなと思います。