次の状態管理はReduxをやめてunstatedにする理由

![alt](https://user-images.githubusercontent.com/26253721/39765058-e8d0eae4-531b-11e8-9305-4c852f269517.png)

react nativeでglobal Stateの管理って何使ってますか？ reduxですか？mobxですか？
両方とも堅牢なライブラリですが、記述量が多いし学習量も多いです。
今、reactを使ってる方、新しく入ってきた人、reduxについてこれてますか？
react初心者には上の二つは厳しいです。。。
今、海外ではぐんぐん伸びてきている超軽量state管理ライブラリ「unstated」使ってみませんか？
global stateをsetStateで変更するため、学習コストがとても低いです。
私はreduxからunstatedに乗り換えたら開発工数が半分になりました。
超おすすめです。

## unstatedとは
1. React標準のContextAPIを超薄く拡張したライブラリ。
2. 学習コストが低く、シンプルでプロトタイプの作成に適している。
3. わずか４００行で書かれ、 サードパーティーのライブラリを使わず純粋なreactのみで書かれている。
4. reactのみで書かれているので、テストが簡単で、ベテランエンジニアにはこれが嬉しい。
5. storeの永続化のためのunstated-persist(遅いが、、、) デバッグのためのunstated-debugなど、エコシステムが充実している。

## 実際に使ってみよう。
以下は純粋なreactで書かれたカウンターアプリだ。まだunstatedは入っていない。

```jsx
class Counter extends React.Component {
  state = { count: 0 }
  increment = () => {
    this.setState({ count: this.state.count + 1 })
  }
  decrement = () => {
    this.setState({ count: this.state.count - 1 })
  }
  render() {
    return (
      <View>
        <Text>{this.state.count}</Text>
        <Text onClick={this.decrement}>-</Text>
        <Text onClick={this.increment}>+</Text>
      </View>
    )
  }
}
```

## 上のコードをunstatedを使って、Viewとロジックを分離してみる。
unstatedでは３つの概念がある。reactのcontextAPIを触ったことがある人ならすぐに馴染める。

1.Container
global stateを記述するコンポーネント。reduxとmobxでいうstore
グローバルなstateの変更と保管を担当。
つまり、巨大なJSONと、そのJSONを変更するためのメソッド群
setStateで、unstatedのstoreの中身のJSONを書き換える。

2.Subscribe
ContainerのメソッドやStateを、Subscribeで囲ったコンポーネントに渡す。

3.Provider
Providerで囲ったコンポーネントの中で、Subscribeを使えるようにするメソッド。

## unstaed を使って書いた例
純粋なreactっぽく書ける。

```jsx
import React from 'react'
import { Provider, Subscribe, Container } from 'unstated'
import {Text, View} from 'react-native'

class CounterContainer extends Container {
  state = {
    count: 0
  }

  increment() {
    this.setState({ count: this.state.count + 1 })
  }

  decrement() {
    this.setState({ count: this.state.count - 1 })
  }
}

function Counter() {
  return (
    <Subscribe to={[CounterContainer]}>
      {counter => (
        <View>
          <Text onClick={() => counter.decrement()}>-</Text>
          <Text>{counter.state.count}</Text>
          <Text onClick={() => counter.increment()}>+</Text>
        </View>
      )}
    </Subscribe>
  )
}

export default App = () => (
  <Provider>
    <Counter />
  </Provider>
)
```

##　テストもとても簡単
unstatedは純粋なreact コンポーネントなので、以下のようにとてもシンプルにテストが書ける。
シニアエンジニアにはこれが嬉しいはず！

```jsx
test('counter', async () => {
  let counter = new CounterContainer()
  assert(counter.state.count === 0)

  await counter.increment()
  assert(counter.state.count === 1)

  await counter.decrement()
  assert(counter.state.count === 0)
})
```

## ちょっと残念なところ。
unstatedでは、Subscribeの外側では、containerのメソッドを使うことはできない。
つまり、componentDidMoutとかの中で、unstatedのstateを変更するには一工夫する必要がある。

つまりHOCを使う必要がある。
以下のようにコンポーネントをSubscribeで囲うのが一般的な使い方だ。

```jsx
class Counter extends Component {
  componentDidMount() {
    this.props.counter.increment()
  }

  render() {
    const { counter } = this.props
    return(
      <View>
        <Text onClick={() => counter.decrement()}>-</Text>
        <Text>{counter.state.count}</Text>
        <Text onClick={() => counter.increment()}>+</Text>
      </View>
    )
  }
}

const CounterWrapper = () => (
  <Subscribe to={[CounterContainer]}>
    {counter => <Counter counter={counter} />}
  </Subscribe> 
)

export default CounterWrapper
```

##react navigationnと一緒に使う時は、HOCの名前でroutingにマップされるのに注意。
もし、unstatedとreact-navigationを使って、画面が真っ白になるバグが出たら、名前が正しくimportされているか確認しよう。HOCを使うと、react navigationでは、画面が真っ白になるバグが起こりやすい。HOC react navigationでググって解決しよう。

以下は正しい例

```jsx
const CounterWrapper = () => (
  <Subscribe to={[CounterContainer]}>
    {counter => <Counter counter={counter} />}
  </Subscribe>
)

export const HomeStack = createStackNavigator({
　　CounterWrapper,
　　ScreenB,
　　ScreenC,
})
```