React Native Navigation 導入メモ

## 前提

※ この記事はiOSアプリを対象に述べています。

```bash
$ date
2017年 3月19日 日曜日 17時09分47秒 JST

$ yarn -V
0.21.3

$ react-native -v
react-native-cli: 2.0.1
react-native: 0.42.3
```

## React Native Navigation とは

ReactNative標準Navigationの微妙なところを改善しようとしている代替パッケージ。詳細はREADMEほかを参照。筆者の導入モチベーションとしては、__標準のNavigatorIOSだとReduxにてpropsの更新を伝えられないのを解決できる__点でした。

### :globe_with_meridians: [wix/react\-native\-navigation](https://github.com/wix/react-native-navigation)

<img width="530" alt="Real world examples" src="https://qiita-image-store.s3.amazonaws.com/0/47035/d801508d-5fdd-0c5c-de69-baede0806ce6.png">


## 導入前の準備

本パッケージを導入するにあたって、標準で想定されているコードとどう違うのかを把握したいところ。なのでまずは、最小限のReactNative新規アプリを用意します。ここでは、自動生成されるコードをさらに削って見通しを良くしています。

```bash
$ react-native init AwesomeProject
$ cd AwesomeProject
$ react-native run-ios
```

```js:index.ios.js
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

class AwesomeProject extends Component {
  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>
          Welcome to React Native!
        </Text>
      </View>
    );
  }
}

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
```

<img width="250" alt="iOS Simulator Image (Before)" src="https://qiita-image-store.s3.amazonaws.com/0/47035/dabb45b6-4361-a4a8-42bc-53da434589f0.png">


## 導入の手順

ドキュメントはサイトにちゃんとまとめられています。 ReactNative の古いバージョンについて触れられていたり、ややこしいので__本記事冒頭の前提をもと__に簡潔に説明します。これをお読みになっているあなたが導入するときには事情が変わっているかもしれないので、下記のリンクから併せてご確認ください。

- [React Native Navigation \- truly native navigation for iOS and Android](https://wix.github.io/react-native-navigation/#/)

#### ざっくり全体の流れ

0. パッケージをインストールする
0. Xcode にライブラリをリンクする
0. `AppDelegate.m`を編集する
0. `index.ios.js`を編集する

### 1. パッケージをインストールする

```bash
$ yarn add react-native-navigation@next
```
```bash:Result
yarn add v0.21.3
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved 0 new dependencies.
✨  Done in 3.52s.
```

### 2. Xcode にライブラリをリンクする

```bash
$ react-native link
```
```bash:Result
Scanning 552 folders for symlinks in /Users/syon/repo/AwesomeProject/node_modules (3ms)
rnpm-install info Linking react-native-navigation android dependency 
rnpm-install info Android module react-native-navigation has been successfully linked 
rnpm-install info Linking react-native-navigation ios dependency 
rnpm-install info iOS module react-native-navigation has been successfully linked
```

### 3. `AppDelegate.m`を編集する

`ios/AwesomeProject/AppDelegate.m` にて、下記のコードで既存の RCTRootView 関連のコードと置き換えます。詳細は __[サンプルアプリの実際のコード](https://github.com/wix/react-native-navigation/blob/master/example/ios/example/AppDelegate.m)__ を参考にしてください。私は下記画像の通り編集しました。

```objc
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
[[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation];
```

![AppDelegate.m](https://qiita-image-store.s3.amazonaws.com/0/47035/d26fc126-448e-0f50-2ac2-5fb8b9e31054.png)


### 4. `index.ios.js`を編集する

上記との差分を見れば、何をどうしたかは明らかでしょう。ここではタブ１つでアイコンもなしという寂しい状況ですが、まずは動かなくては話になりません。ポイントとしては `AppRegistry` まわりのことはこのパッケージがやってくれること、`Navigation.registerComponent`の第一引数であるスクリーンIDは特にアプリの名称と一致していなくても動作する、といったところでしょうか。

```js:index.ios.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { Navigation } from 'react-native-navigation';

class Welcome extends Component {
  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>
          Welcome to React Native!
        </Text>
      </View>
    )
  }
}

function registerScreens() {
  Navigation.registerComponent('example.WelcomeTabScreen', () => Welcome);
}
registerScreens();

Navigation.startTabBasedApp({
  tabs: [
    {
      label: 'Welcome',
      screen: 'example.WelcomeTabScreen',
      title: 'Welcome'
    },
  ]
});
```


## Done!

<img width="250" alt="iOS Simulator Image (After)" src="https://qiita-image-store.s3.amazonaws.com/0/47035/d8114ea8-62c1-1538-ddf9-14de42c5788b.png">

#### see also:

- [react\-native\-navigation/example at master](https://github.com/wix/react-native-navigation/tree/master/example)  
  本パッケージのサンプルアプリ

<!---->

- [junedomingo/movieapp: Discover Movies and TV shows \- React Native](https://github.com/junedomingo/movieapp)  
  Reduxを利用したサンプル


## TIPS

### ステータスバーを制御するには

Xcode にてコードから制御することを許可する

- [Styling the StatusBar](https://wix.github.io/react-native-navigation/#/styling-the-navigator?id=styling-the-statusbar)  
  Xcode > TARGETS > Info > View controller-based status bar appearance > `YES`