Tabの中にTabを出す（それもページ全体ではなくコンテンツの１部として）


## やりたいこと

react-navigatorで普通にネストすると画面いっぱいになります（そうしないやり方もありますが、めんどくさい）。今回やりたいのは画面の一部としてTabコンテンツを利用したい（かつなるべく簡単に）。

react-navigationのtab-navigationを使うより、そのベースになっているreact-native-tab-viewを使う方が簡単らしいので試してみました。


![スクリーンショット 2020-01-06 9.56.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/47a6e1b9-a851-3a60-e251-cc103b6bc6a0.png "スクリーンショット 2020-01-06 9.56.31.png")


## 準備

私はexpoを使ってるのですが、2020年1月6日現在、いろいろ依存関係の問題などがあるのでモジュールのインストールはやや複雑？です。

### 場所の確保

まず場所の確保。言語とかはお好みで。

```bash
expo init innerTab
cd innerTab
```

### 必要モジュールのインストール

#### navigationの必須モジュール

まず、react-navigationと必須なモジュール。react-navigationのページにある通りにインストールします。

```bash
expo install react-navigation react-native-gesture-handler react-native-reanimated react-native-screens
```

#### 各種ナビゲーション

次に必要なnavigationをインストール。

```bash
expo install npm react-navigation-stack react-navigation-tabs   
```

#### エラー対応

下記2つのモジュールが無い！とエラーがでるのでインストール。

```bash
expo install react-native-safe-area-context @react-native-community/masked-view
```

#### 内部Tab用モジュールインストール

内部Tabを作成するためのモジュールをインストール。アイコン表示も試したいので追加。

```bash
expo install react-native-tab-view react-native-vector-icons
```

## 実装

で、実装。まずApp.jsでレイアウトを行います。
全体を包むTab（HomeTab）を作って、そのうちのHome.jsに子Tabを記述します。

>なお、私の趣味でStackNavigationでラップしています（必須ではありません）。

```js:App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';

//import screens
import Home from './screens/Home';
import Profile from './screens/Profile';
import Info from './screens/Info';
import News from './screens/News';

//HomeStack
const HomeStack = createStackNavigator(
    {
        Home: {
            screen: Home,
        }
    }
);

const ProfileStack = createStackNavigator(
    {
        Profile: {
            screen: Profile,
        }
    }
);

//HomeTab
const HomeTab = createBottomTabNavigator(
    {
        _Home: {
            screen: HomeStack,
        },
        _Profile: {
            screen: ProfileStack
        }
    }
);

//AppContainer
const AppContainer = createAppContainer(HomeTab);

class App extends React.Component {
    render() {
        return (
            <AppContainer />
        );
    }
}

export default App;
```

いよいろ本丸の子Tab。普通は分けてもいいのでしょうけど、Home.jsに全部書いちゃいます。

```js:screens/Home.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/FontAwesome';
import Info from './Info';
import News from './News';

class Home extends React.Component {

    state = {
        tabIndex: 0,
        tabRoutes: [
            //普通にアイコン表示
            { key: 'info', title: 'お知らせ', renderIcon: (color) => (<Icon size={24} name="home" color={color} />) },
            //titleと横並び（titleは消す）
            { key: 'news', renderIcon: (color) => (<View style={{ flexDirection: "row", alignItems: 'center' }}><Icon size={24} name="cog" color={color} /><Text style={{ marginLeft: 5 }}>aaa</Text></View>) }
        ],
    }

    render() {
        return (
            <View style={{ flex: 1 }} >
                <View style={{ flex: 1 }}>
                    <Text>Content1</Text>
                </View>
                <TabView
                    style={{ flex: 1 }}
                    navigationState={{
                        index: this.state.tabIndex,
                        routes: this.state.tabRoutes,
                    }}
                    renderScene={SceneMap({
                        info: Info,
                        news: News,
                    })}
                    onIndexChange={(index) => this.setState({ tabIndex: index })}
                    renderTabBar={(props) => (
                        <TabBar
                            {...props}
                            style={{ backgroundColor: "#ccc" }}
                            labelStyle={{ color: "#000" }}
                            indicatorStyle={{ backgroundColor: "#A8E9FF", height: "100%" }} //heightを100%にすれば背景色となる・・・
                            renderIcon={({ route, color }) => route.renderIcon(color)}
                            activeColor={"#00f"}
                            inactiveColor={"#aaa"}
                        />
                    )}
                />
            </ View>
        );
    }
}

export default Home;
```

その他のページはただページ名を中央に表示しているだけ。Info, Profile, Newsなど。。。
書きを参考にscreensフォルダの中に着くるとよいでしょう。

```js:Info.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

class Info extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Info</Text>
            </View>
        );
    }
}

export default Info;
```

以上です。