React Navigationのnavigateとpushは何が違うのか

##はじめに
つい最近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ってなんぞや...
単語の意味の通り、経路みたいなものだと思っています。

以下のコードを見てください。

```React
// 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に飛んでみましょう。

```javascript
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`を使用しても画面は遷移されません。

```javascript
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.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1789530/a79fbab8-8e5b-cc63-c1fa-8591e4772fae.png)


###navigation.navigateを使う場面でnavigation.pushを使ってしまうとどうなるのか

単純に画面に遷移するはずが新しく経路を作ってしまいます。

ここからは私個人がこんな問題が起きるんじゃないかな？と予想していることなのですが...

経路を作るたびすなわち`navigation.push`を使うたびにheaderには自動的に一つ前の画面に戻ることができる`nabigation.goBack()`という機能が提供されます。

`push()`したときにこの`goBack()`を使うと`push()`を実行した一つ前の画面に戻ります。上の例では画面が二つしかないのでわかりにくいのですが、画面の数がもっと増えてくると画面を操作して遷移しているうちに意図した画面に戻れなくなる可能性があるのかなと思います。