ReactNativeでモーダルを使う


普段Navigation関係はReact-Navigationを利用していて、React-NavigationにもModalを出す機能はあるが、StackNavigationを入れ子にする必要がある等、ちょっと癖があるので、react-native-modalを試してみます。

## やりたいこと

下記のようなモーダルを出す。

![スクリーンショット 2019-09-15 8.50.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/661073d9-2bd6-a3d7-a07d-6665ebb11904.png "スクリーンショット 2019-09-15 8.50.38.png")


## 準備

```bash
npm install --save react-native-modal
```


## 実装

これで動く。
基本的に\<Modal>\</Modal>でコンテンツを囲ってやればいい。

```js:App.js
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Button } from 'react-native';
import Modal from "react-native-modal";


export default class App extends React.Component {

    state = {
        isModalVisible: false
    }

    toggleModal = () => {
        this.setState({ isModalVisible: !this.state.isModalVisible });
    }

    render() {
        return (
            <SafeAreaView style={{ flex: 1 }}>
                <Text>App</Text>
                <Button
                    title="Show modal"
                    onPress={this.toggleModal}
                />
                <Modal isVisible={this.state.isModalVisible}>
                    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: "#fff" }}>
                        <Text>Modal Content</Text>
                        <Button
                            title="Close modal"
                            onPress={this.toggleModal}
                        />
                    </View>
                </Modal>
            </SafeAreaView>
        );
    }
}
```

## 応用（コンテンツの外だし）

Modalで表示する内容が複雑になってくると、メイン？コンテンツの中に定義するのはうざい。
Modalで表示する内容を外部ファイルにしてみる。

### Child.js

基本的には\<View>\</View>部分を切り出しただけだが、モーダルを閉じるためのメソッドをprops経由で受けとっている。

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

export default class Child extends React.Component {

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: "#fff" }}>
                <Text>Modal Content</Text>
                <Button
                    title="Close modal"
                    // イベントをpropsでもらう
                    onPress={this.props.nav.toggleModal}
                />
            </View>
        );
    }
}
```

### App.js

Child.jsを読み込み、this全体をnavという名前でpropsで渡している。

```js:App.js
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Button } from 'react-native';
import Modal from "react-native-modal";

import Child from './Child';

export default class App extends React.Component {

    state = {
        isModalVisible: false
    }

    toggleModal = () => {
        this.setState({ isModalVisible: !this.state.isModalVisible });
    }

    render() {
        return (
            <SafeAreaView style={{ flex: 1 }}>
                <Text>App</Text>
                <Button
                    title="Show modal"
                    onPress={this.toggleModal}
                />
                <Modal isVisible={this.state.isModalVisible}>
                    <Child nav={this} />
                </Modal>
            </SafeAreaView>
        );
    }
}
```

### モーダルの大きさ

もちろん、モーダル自体の大きさもstyleで調整可能。

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

export default class Child extends React.Component {

    render() {
        return (
            <View style={{ justifyContent: 'center', alignItems: 'center', backgroundColor: "#fff", height:300 }}>
                <Text>Modal Content</Text>
                <Button
                    title="Close modal"
                    // イベントをpropsでもらう
                    onPress={this.props.nav.toggleModal}
                />
            </View>
        );
    }
}
```

![スクリーンショット 2019-09-15 9.00.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/d7c7ef4d-ed38-b5ca-9534-5e85b833bff0.png "スクリーンショット 2019-09-15 9.00.04.png")