RN応用編１：Drawer Navigatorをハンバーガーメニューで表示させる

基礎編からの続きです。

## シリーズ

* [React-Navigatorを利用してみる（基礎編）](https://qiita.com/zaburo/private/5b69a65db1b4d181896a)
* [RN応用編１：Drawer Navigatorをハンバーガーメニューで表示させる](https://qiita.com/zaburo/private/aaf198c79520dbaa48e2)→この記事
* [RN応用編２：TabやDrawerメニューにアイコンを設定する](https://qiita.com/zaburo/private/05c41190726cbcb17fdf)
* [RN応用編３：Reduxで値の取り回し](https://qiita.com/zaburo/private/c7df04fa1d53fd08559c)

## 概要

基礎編でDrawer Navigationを追加しましたが、そのままでは、利用者は存在に気づきません。そのため、ヘッダー部分にハンバーガーメニューを追加して、Drawerを開くようにします。

<img width="195" alt="スクリーンショット 2018-10-28 8.55.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/3902a482-9848-0478-bb14-d4a8ec209196.png">


なお、Tab NavigationやSingleページ？（Stack Navigation以外）ではヘッダにメニューを追加できないようなので、その対応方法も書きます。

## ひとまずハンバーガーメニューを追加する

### アイコンが使えるようにする

ハンバーガーのアイコンを利用したいのでモジュールをinstallします。

```bash
npm install --save react-native-vector-icons
```
### 実装してみる

実装してみます。
実装する場所は、コンポーネントに直書きするかcreateStackNavigator()の記述をいじるかの2種類あります。
が、ここではコンポーネントに記述してみます（本家サイトがそうしてるので）。

```diff:Stack1.js
import React from 'react';
import { View, Text, Button } from 'react-native';
+import Icon from 'react-native-vector-icons/FontAwesome';

export default class Stack1 extends React.Component {
+
+    static navigationOptions = ({navigation}) => ({
+        title:'Stack1',
+        headerLeft:(
+            <Icon name="bars" size={24} onPress={()=>{navigation.openDrawer()}} style={{paddingLeft:20}}/>
+        ),
+    });

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Stack1</Text>
                <Button
                    title='GoTo Stack2'
                    onPress={() => this.props.navigation.navigate('Stack2')}
                />
            </View>
        );
    }
}
```

### 参考： createStackNavigator()での書き方

下記のような感じです。お好みで。

```js:App.js（抜粋）
const Stack = createStackNavigator(
  {
    Stack1: {
      screen: Stack1,
      navigationOptions: ({ navigation }) => ({
        headerLeft: (
          <Icon name="bars" size={24} onPress={() => { navigation.openDrawer() }} style={{ paddingLeft: 20 }} />
        ),
      })
    },
    Stack2: { screen: Stack2 },
  },
  {
    initialRouteName: 'Stack1'
  }
);
```

### 動作確認

<img width="545" alt="スクリーンショット 2018-10-27 20.22.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/69488a56-4695-f55d-6ad4-8bf1a0b8f01f.png">

ハンバーガーメニューが表示されました。

## Stack Navigator以外でもハンバーガーメニュー（ヘッダに何かを）表示する

ハンバーガーメニューを利用するのならUIの統一性という意味でTabや普通のページ（ここではSingle）でも表示させたいと思うのが人の心と言うものです。ところが、普通にやると表示されません。

### 普通に記述してみる（表示されない確認）

では、Tab1.jsにStack1.jsと同様な記述を追加してみます。

```diff:Tab1.js
import React from 'react';
import { View, Text, Button } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

export default class Tab1 extends React.Component {

    static navigationOptions = ({navigation}) => ({
        title:'Tab1',
        headerLeft:(
            <Icon name="bars" size={24} onPress={()=>{navigation.openDrawer()}} style={{paddingLeft:20}}/>
        ),
    });

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Tab1</Text>
            </View>
        );
    }
}
```

実行してもハンバーガーメニューは表示されません。Sigle1.js等でも同様です。

<img width="545" alt="スクリーンショット 2018-10-27 22.01.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/bf8242a7-76d4-8fbc-a7e9-b68da1e4eb97.png">

どうやらStack Navigation以外ではヘッダ（少なくともアイコン等）の表示はできないようです。

### Stack Navigation以外でもヘッダを表示させる（本題）

Tab Navigatorや一般のページでヘッダを表示させるためには、以下のようにStack Navigatorでラップ（入れ子に）してやればいいようです。なんかHackチックでいやですが仕方ありません。

```diff:App.js（抜粋）
//Tab
const Tab = createBottomTabNavigator(
    {
        Tab1: { screen: createStackNavigator({ Tab1: { screen: Tab1 } }) },
        Tab2: { screen: createStackNavigator({ Tab2: { screen: Tab2 } }) },
    }
);
```

こうすることでTab1.jsでもハンバーガーメニューが表示されるようになります。

<img width="545" alt="スクリーンショット 2018-10-27 22.10.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/2e721f57-c4f9-2ae1-fbbc-f55c64d5b08c.png">

Single1.js等も必要な箇所でラップすることで表示可能となります。

```diff:App.js（抜粋）
//drawer
const Drawer = createDrawerNavigator(
  {
    Stacks: { screen: Stack },
    Tabs: { screen: Tab },
+    Single1: {
+      screen: createStackNavigator({
+        Single1: { screen: Single1 }
+      })
+    },
    Single2: { screen: Single2 }
  }
);
```

<img width="545" alt="スクリーンショット 2018-10-27 22.13.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/55188/83c66cdf-70a3-3f5a-7812-2f96cb9c4cc3.png">

これでTab Navigatorや一般ページでもハンバーガーメニューが表示されるようになりました。
Single1.js等にも追加して試してみてください。

## 雑感

iPhoneのノッチ対応等を考慮すれば、RNを使うのであればおおよそのページをStackNavigatorでラップしておくのもありかなと思っています。
問題は、Redux等でうまく動作するかです（そのうち検証しますが）。

## リンク

[RN応用編２：TabやDrawerメニューにアイコンを設定する](https://qiita.com/zaburo/private/05c41190726cbcb17fdf)