面倒な人向けの Redux入門 (with React)

State 管理 の Redux を最近学び始めたので、そのメモ。

## １：なぜ Redux が必要か？
　State 管理 を 複数のコンポーネントでする場合、親コンポーネントから孫コンポーネントその下のひ孫コンポーネント...とコンポーネントが増えれば増えるほど Prop でデータを渡すことが多くなることがあります。
　その場合の、データのバケツリレー（親コンポーネントからひ孫コンポーネントにデータを渡す場合の、息子・孫コンポーネントのProp渡し）を省略するために、Redux を使う。
　Redux を使えば、一つの大きな State を、親コンポーネントからひ孫コンポーネント始めその下のコンポーネントまで、__１回の呼び出しでアクセスできる__ようにできる。フォームの細かい State など例外を除けば、この大きな State で状態を管理してみよう、というのが Redux。

※　正確にコードを読んだわけでも Redux について熟練でいるわけでもないので、意訳や解釈が間違っている部分についてはご容赦ください。

## ２：Redux @ コード

　ここでは、React のチュートリアルのコードで、Redux @ React の簡単な概要について説明します。
　以下のサイトを参照しました。[『Redux』を用いて状態管理をしてみよう！](https://qiita.com/micropig3402/items/ca6f14f92d6238a0aade)

__1. 下準備__

   Redux を使う下準備に State を作る必要があります。以下のコードを src/index.js などに加えます。（※ reducers については後で説明します）

+ createStore & Provider
 
```Js:src/index.js
import {createStore} from "redux"
import {Provider} from "react-redux"
import reducer from "reducers"
// 省略
const store = createStore(reducer)
//
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
```

これで、reducer のデータを参照した 大きな State が、作成され、Provider の子要素である App で参照できるようになります。


__2. 大きな State のアクセス方法（書き込み）__

　アクセスには、読み出し と 書き込みがあります。ここでは、「簡単な読み出し」と「簡単な書き込み」を説明します。

+ 簡単な読み出し

　上のコードの store を持っている場合は、下のコマンドで store の中の State を取得できます。

```Js:src/index.js
console.log(store.getState())
```

　簡単ですね。

+ 簡単な書き込み (更新)

　書き込みで必要になるのが、Action と Reducer になります。例えを使って意訳で言えば、__「Action は API の URL送信(とパラメーター)・Reducer は API内部のロジック」__になります。

　Action と Reducer は、例えば下のようなファイルで書きます。

　　- Action 

　このファイルにある textChange を 呼び出すと、type が TEXTCHANGE である操作を Reducer から探してもらい、引数から取り出した textValue と textLength を引数として渡します。

　API で言えば、type が URLで、`(textValue, textLength)` がパラメーターの部分です。

```Js:src/actions/index.js
export const TEXTCHANGE = "TEXTCHANGE"
export const textChange = (textValue, textLength) => {
  return {
    type: TEXTCHANGE,
    textValue: textValue,
    textLength: textLength,
  };
};
```

どのようにアクセスするかというと store があるファイルからは、以下のようにしてアクセスできます。

```Js:src/index.js
import {addTodo} from "./actions"
//省略
let text_hoge = "hogehoge"
store.dispatch(textChange(text_hoge, text_hoge.length))
```

ですが、Action はあくまでも APIのURL入力だけのようなものだけなので、API内部のロジックが必要になります。それが Reducer です。

　　- Reducer

Reducer では、API の内部ロジックのようなものを作っていきます。

```Js:src/reducers/index.js
import {combineReducers} from 'redux';
import text from './text';

export default combineReducers({text});
```

このファイルの関数名「combineReducers」で、内部ロジックを作っている reducer ファイルをまとめています。なので、「src/reducers/text.js」にある内容がまとめられた前のものになります。

```Js:src/reducers/text.js
import {TEXTCHANGE} from '../actions';

const initialState = {textLength: 0, textValue: ''};

export default (state = initialState, action) => {
  switch (action.type) {
    case TEXTCHANGE:
      return {textValue: action.textValue, textLength: action.textLength};
    default:
      return state;
  }
};
```

action に、actions (APIのURLとパラメーターのようなもの) からの入力が入ります。ここでは、type で条件分岐して、どの内部ロジックの処理をするか分岐させています。

__3. 読み出し__

　ここまでで、コマンド上での読み出しと書き込みに触れましたが、ここでは React のコンポーネント上からのアクセスについて触れます。

+ 読み出し

　読み出しをするには、読み出しが必要なファイルで、以下のような Funtion を作ります。

```js:
const mapStateToProps = state => {
  return {
    textValue: state.text.textValue,
    textLength: state.text.textLength,
  };
};
```

これで、関数名の意味のまま、上記の `store.getState()` では state だった textValue と textLength の内容が、props に入ります。

また、書き込み をコンポーネントから行うために、以下のような Function を作ります。

```js:
const mapDispatchToProps = dispatch => {
  return {
    textChange: (textValue, textLength) =>
      dispatch(textChange(textValue, textLength)),
  };
};
```

dispatch は 関数コンポーネントで `const hoge = ({dispatch}) => {` で取得して、利用することもできます。

__4.まとめ__

　Redux は、Props のバケツリレーを避けるために、大きな State を管理してくれる。State の読み出しは、store を作成したファイルでは楽だが、そうでない場合は `mapStateToProps`が必要で、書き込みには、dispatch が必要。