React-Reduxの使い方 (ReactとReduxの接続)

個人的なメモも兼ねて。

## `src/index.js`でやること
### 1. `createStore`のメソッドを`Redux`からimportする。

`STORE`を作成するためのメソッド。
引数に`reducer`を指定する(後述)。

```js:src/index.js
import { createStore } from 'redux';
```

### 2. `Provider`コンポーネントをimport

ReduxをReactで使用するためのMWである`react-redux`から、Reactプロジェクトで使用することのできる`Provider`コンポーネントをimportし、設置する。

#### `Provider`コンポーネントって何？
[React Reduxの公式ドキュメント](https://react-redux.js.org/api/provider#overview)にもあるように、`Provider`コンポーネントにネストされている範囲だけが、`react-redux`の機能の一つである`connect()`でconnectされたコンポーネントを扱えるようになるらしい。
> Normally, you can’t use a connected component unless it is nested inside of a`<Provider>`.

`Provider`コンポーネントは`store`と言うpropsのみ受け付けている。文字通りこのpropsには`createStore()`で作成した`STORE`を渡す。

```js:src/index.js
import { Provider } from 'react-redux';

~~~~~中略~~~~~

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}> 
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
```

### 3. `STORE`に渡すための`REDUCER`をimport

`REDUCER`は他のファイルで定義しておく。
よく見かけるのは`src/reducers`ディレクトリを切ってその中に目的別のreducerファイルを作成していく手法。

複数のファイルにまたがる`REDUCER`を一つにまとめて`src/index.js`で`STORE`に渡す方法は以下を参照。
[Reactアプリ内でのReduxの複数のReducerを一つにまとめる方法 - Qiita](https://qiita.com/yukiyohure0923/items/37320d22dff84127feb6)

``` js:REDUCERをまとめてimport
import rootReducers from "./reducers"; // 指定がない場合はwebpackがデフォルトでindex.jsというファイルを指定してくれる
```

## Reduxを使用するときにやること

### ReactとReduxの接続 `connect()`

**登場人物たち**
- **mapStateToProps** :`STORE`が持っているstateをpropsに入れて子コンポーネントへ渡す。
- **mapDispatchToProps** :`DISPATCH`を呼び出す関数をpropsに入れて子コンポーネントへ渡す。

```js:mapStateToPropsについて
const mapStateToProps = (state) => { // Issueコンポーネント内で使用するstateを限定する役目
  return {
    // stateオブジェクトから指定できるのは、src/reducers/index.js でrootReducerにまとめたときのオブジェクトのkey名
    // key名がコンポーネントで受け取るpropsの名前になる
    // なので、子コンポーネントでは「issue」という名前で参照可能。
    issue: state.issue.data,
  };
}
```

```js:mapDispatchToPropsについて
/*
子コンポーネントからdispatchするときに、わざわざ `dispatch(actionCreator(追加したい要素))`しなくても、
この場合だと `addContents(追加したい要素)` でstoreにdispatchできるようになる。
*/
const mapDispatchToProps = dispatch => {
  return {
    addIssue: (payload) => {
      dispatch(actions.addIssue(payload));
    },
  }
}
```

**`connect()`の書き方**

```js:connect()の書き方
const ContainerInMiddle = connect(
  mapStateToProps,
  mapDispatchToProps
)(ChildComponent);
```

### `Container Components`(reduxと接続したreactのコンポーネント)のコード例   

```js
import * as actions from '../actions';
import { connect } from 'react-redux';
import IssueContents from '../components/organisms/IssueContents';

const mapStateToProps = (state) => { // Issueコンポーネント内で使用するstateを限定する役目
  return {
    // stateオブジェクトから指定できるのは、src/reducers/index.js でrootReducerにまとめたときのオブジェクトのkey名
    // key名がコンポーネントで受け取るpropsの名前になる
    // なので、子コンポーネントでは「issue」という名前で参照可能。
    issue: state.issue.data,
  };
}

/*
  子コンポーネントからdispatchするときに、わざわざ `dispatch(actionCreator(追加したい要素))`しなくても、
  この場合だと `addContents(追加したい要素)` でstoreにdispatchできるようになる。
*/
const mapDispatchToProps = dispatch => {
  return {
    addIssue: (payload) => {
      dispatch(actions.addIssue(payload));
    },
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(IssueContents);
```

## 参考

▷[Reduxのconnectについて](https://qiita.com/macotok/items/ddbebfbb7dd3d834d86e)
▷[Basic Tutorial \| React Redux](https://react-redux.js.org/introduction/basic-tutorial)
▷[ReactとReduxで管理するstateの分け方｜Playground発！アプリ開発会社の技術ブログ](https://tech.playground.style/javascript/state-management/)