React Navigation(stack)の簡単な使い方とScreen間の値の受け渡し(reduxなし）


## 準備

今回はexpコマンドを利用してみます。create-react-native-appでも基本は同じ。

```bash
exp init stack
>blank

cd stack
npm install --save react-navigation
```

> You must install peer dependencies yourselfというWarningが沢山でますが、無視（動作に問題ないようです）。


## 基本実装

実装していきます。はじめから存在しているApp.jsを編集していきます。編集は下から上に進む感じです。
シンプルでわかりやすいですね。

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


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

//Home
class HomeScreen extends React.Component{
  render(){
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>Home</Text>
        <Button
          title='Link to About'
          onPress={() => this.props.navigation.navigate('About')}
        />
      </View>
    );
  }
}


//RootStack
const RootStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    About: {
      screen: AboutScreen,
    }
  },
  {
    initialRouteName: 'Home',
  }
);

//App
export default class App extends React.Component {
  render() {
    return (
      <RootStack/>
    );
  }
}
```

## Screen間での値の受け渡し

いくつかのやり方があるようですが、今回はPropsとGlobal変数を利用するやり方を検証してみます。

>今回はReduxは使わないでおきます。

### props

受け渡し（送信）は、リンクの際のthis.props.navigation.navigate('About',{Data})の第二引数に指定します。
受け取りは、this.props.navigation.state.params.Dataという感じで取得できるようです。

```diff:App.js
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } from 'react-navigation';


class AboutScreen extends React.Component{
  render() {
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>About</Text>
+        <Text>{this.props.navigation.state.params.User.name}</Text> //受け取り
      </View>
    );
  }
}

class HomeScreen extends React.Component{
  render(){
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>Home</Text>
        <Button
          title='Link to About'
+          onPress={() => this.props.navigation.navigate('About',{User:{name: 'hoge', age: 33}})} //送信
        />
      </View>
    );
  }
}


const RootStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    About: {
      screen: AboutScreen,
    }
  },
  {
    initialRouteName: 'Home',
  }
);

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

```

### Globals.js

[ここ](https://stackoverflow.com/questions/33492943/global-variable-constant-in-react-native/36994650#36994650)に書いているやり方です。そのまま利用させていただきます。
まず、App.jsと同じ階層にGlobals.jsを作成し、下記の記述をします。

```js:Globals.js
export default {
  STORE_KEY: 'a56z0fzrNpl^2',
  BASE_URL: 'http://someurl.com',
  COLOR: {
    ORANGE: '#C50',
    DARKBLUE: '#0F3274',
    LIGHTBLUE: '#6EA8DA',
    DARKGRAY: '#999',
  },
};
```

App.jsにてGlobals.jsを読み込みます。

```diff:App.js
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } from 'react-navigation';
+import GLOBALS from './Globals';


class AboutScreen extends React.Component{
  render() {
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>About</Text>
        <Text>{this.props.navigation.state.params.User.name}</Text>
+        <Text>{GLOBALS.COLOR.ORANGE}</Text>
      </View>
    );
  }
}

class HomeScreen extends React.Component{
  render(){
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>Home</Text>
        <Button
          title='Link to About'
          onPress={() => this.props.navigation.navigate('About',{User:{name: 'hoge', age: 33}})}
        />
+        <Text>{GLOBALS.COLOR.ORANGE}</Text>
      </View>
    );
  }
}


const RootStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    About: {
      screen: AboutScreen,
    }
  },
  {
    initialRouteName: 'Home',
  }
);

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

```

どちらのScreenでも#C50という設定値が参照できています。

#### 値を更新してみる

Globals.js内の値は普通に？更新可能です。
とりあえずDidMountで更新してみます（もちろん元ファイルが書き換わるわけではありません）。

```diff:App.js
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createStackNavigator } from 'react-navigation';
import GLOBALS from './Globals';


class AboutScreen extends React.Component{
  render() {
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>About</Text>
        <Text>{this.props.navigation.state.params.User.name}</Text>
        <Text>{GLOBALS.COLOR.ORANGE}</Text>
      </View>
    );
  }
}

class HomeScreen extends React.Component{
  render(){
    return (
      <View style={{flex:1, alignItems: 'center', justifyContent: 'center'}}>
        <Text>Home</Text>
        <Button
          title='Link to About'
          onPress={() => this.props.navigation.navigate('About',{User:{name: 'hoge', age: 33}})}
        />
        <Text>{GLOBALS.COLOR.ORANGE}</Text>
      </View>
    );
  }
}


const RootStack = createStackNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    About: {
      screen: AboutScreen,
    }
  },
  {
    initialRouteName: 'Home',
  }
);

export default class App extends React.Component {

+  componentDidMount(){
+    GLOBALS.COLOR.ORANGE = '#FFFFFF';
+  }

  render() {
    return (
      <RootStack/>
    );
  }
}
```

上記の実装の場合、HomeのGLOBALS.COLOR.ORANGEの値は#C50となり、Aboutの値は#FFFFFFとなります。setState()ではないので、自動的に更新されたりはしないので注意が必要です(componentWillMount()に実装すれば、どちらも#FFFFFFとなります）。