【React Native】React Navigation を使ってみる（画面遷移編）

# React Navigation
React Navigation は React Native で使用できるルーティングとナビゲーションのコンポーネントです。

https://github.com/react-navigation/react-navigation


# 前提ライブラリ
本記事は、「NativeBase」の導入を前提としています。一からプロジェクトを作成する場合には、以下の記事を参考に環境作成してください。
[【React Native】NativeBase導入](https://qiita.com/keneo/items/d3a36d973c0b89829aa9)

# 環境構築
作成したプロジェクトに対して以下のコマンドで React Navigation を導入します。

```
$ npm install react-navigation --save
```

※Githubのドキュメントには明確な記述はないのですが下記のインストールも明示的に必要みたいです。

```
$ npm install react-native-gesture-handler --save
```

# アプリ作成

## App.js

```js:App.js
import React, {Component} from 'react';
import { createStackNavigator } from 'react-navigation'

import Main from './screens/Main'
import Push from './screens/Push'
import Modal from './screens/Modal'

const MainNavigation = createStackNavigator(
  {
    Main: { screen: Main },
    Push: { screen: Push },
  },
  {initialRouteName: 'Main', mode: 'card', headerMode: 'none'}
)
const NestNavigation = createStackNavigator(
  {
    MainNavigation: { screen: MainNavigation },
    Modal: { screen: Modal },
  },
  {initialRouteName: 'MainNavigation', mode: 'modal', headerMode: 'none'},
)

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <NestNavigation />
    );
  }
}
```

* 全体のルーティングを定義します。具体的には「StackNavigator」を使用して画面を定義しています。
* プッシュ表示させる場合と、モーダル表示させる場合を想定しています。（StackNavigator をネストさせています）
* 画面構成は以下の通りです。
  * メイン画面 （Main.js）
  * プッシュ表示される画面 （Push.js）
  * モーダル表示される画面 （Modal.js）


## Main.js

```js:Main.js
import React, {Component} from 'react';
import { Container, View, Header, Left, Body, Right, Button, Title, Text } from 'native-base';

type Props = {};
export default class Main extends Component<Props> {
  push = () => {
    const { navigation } = this.props
    navigation.navigate('Push')
  }
  modal = () => {
    const { navigation } = this.props
    navigation.navigate('Modal')
  }
  render() {
    return (
      <Container>
        <Header>
          <Left />
          <Body>
            <Title>メイン</Title>
          </Body>
          <Right />
        </Header>
        <View>
          <Button small iconRight  transparent primary onPress={this.push}>
            <Text>プッシュ表示</Text>
          </Button>
        </View>
        <View>
          <Button small iconRight  transparent primary onPress={this.modal}>
            <Text>モーダル表示</Text>
          </Button>
        </View>
      </Container>
    );
  }
}
```

* トップ画面を定義しています。
* プッシュ表示及び、モーダル表示のためのボタンを配置しています。


## Push.js

```js:Push.js
import React, {Component} from 'react';
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';

type Props = {};
export default class Push extends Component<Props> {
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button transparent onPress={() => this.props.navigation.goBack()}>
              <Icon name='arrow-back' />
            </Button>
          </Left>
          <Body>
            <Title>プッシュ</Title>
          </Body>
          <Right />
        </Header>
      </Container>
    );
  }
}
```

* プッシュ表示される画面を定義しています。


## Modal.js

```js:Modal.js
import React, {Component} from 'react';
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';

type Props = {};
export default class Modal extends Component<Props> {
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button transparent onPress={() => this.props.navigation.goBack()}>
              <Icon name='close' />
            </Button>
          </Left>
          <Body>
            <Title>モーダル</Title>
          </Body>
          <Right />
        </Header>
      </Container>
    );
  }
}
```

* モーダル表示される画面を定義しています。

# 動作の様子

## iOS
![ios.gif](https://qiita-image-store.s3.amazonaws.com/0/22218/4c01c45f-bbb5-8b8c-8686-46eec4922b61.gif)

## Android
![android.gif](https://qiita-image-store.s3.amazonaws.com/0/22218/9cb78b05-c8d3-6758-2d25-370add9bfc5c.gif)

* Androidの場合、React Navigation の仕様で、「mode: "card”」、「mode: "modal”」の双方でスタンダードな画面遷移となるようです。（Androidの標準的な画面遷移の仕様に沿っていると思われます）

# リポジトリ
本記事で作成したものは以下で公開していますので、参考にしてください。
https://github.com/k-neo/ReactNativeCourseReactNavigation