Reduxを完全に理解した(〜実装編〜)

Reduxの理論編に引き続き実装編について説明していきます:alien:。

↓↓↓ 理論編についてはこちら ↓↓↓
<a href="https://qiita.com/kzy83/items/7754486696aa2ebb932c" target="_blank">
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516848/4b434418-345b-be87-15a5-2640863cfdf5.png"　/>
</a>


ではコードをもとに説明をしていきます。
今回は簡単なTODOアプリでTODOの追加・削除のみできるものを想定しています。

### Reducer
まずは「**Reducer**」についてですが、理論編で説明したように「**Reducer**」は渡されてきた「**Action**」と現在の状態から新しい「**State**」を作成し返しています。
→「**純粋関数**」で副作用もないですね:clap:

```javascript:reducers.js
import { combineReducers } from 'redux';

export function todoReducers(state={
  list: []
}, action) {
  switch (action.type) {
    case "ADD_TODO":
      return Object.assign({}, state, {
        list: state.list.concat(action.todo)
      });
    case "REMOVE_TODO":
      return Object.assign({}, state, {
        list: state.filter(todo => {
          return action.todo != todo;
        })
      });
    default:
      return state;
  }
};

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

### Action
次にActionですが、これはReducerに渡す情報を返すだけの処理になっています。
TODOを追加する処理と、削除する処理があるのでそれぞれのActionを作成しています。
```javascript:action.js
export function addTodo(todo) {
  return {
    type: "ADD_TODO",
    todo
  }
}

export function removeTodo(todo) {
  return {
    type: "REMOVE_TODO",
    todo
  }
}
```

### Store
これに関しては、Storeを作成しているだけですね:point_up:
```javascript:store.js
import { createStore } from 'redux';
import reducers from './reducers';

const store = createStore(reducers);

export default store;
```

### Entry部分
index.jsについては最初のEntryの部分で、コンポーネントの一番親と言っていい部分です。
またProviderとありますが、Providerはpropsで子コンポーネントに渡さずとも、コンポーネントツリー内でデータを渡すことができるものとなっています。

```javascript:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
import registerServiceWorker from './registerServiceWorkder';

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

registerServiceWorker();
```

### App（実際のTODOアプリメイン処理）
先ほど、providerをindex.jsで使用しているので、mapStateToPropsのようなfunctionを作成しStoreの中身をバケツリレーでなくとも受け取ることができます。
追加処理については、テキストボックスの中身に変更が加わると、このコンポーネント（App）内の「**State**」にセットします。そして、追加ボタンを押すとその「**State**」を「**Action**」に詰めて「**Dispatch**」します。

削除処理についても「**Action**」に詰めて「**Dispatch**」するところは同様で、「**Store**」内の「**State**」のTODOリストでループして、各TODOを「**Action**」に詰めて「**Dispatch**」しています。

```javascript:App.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { addToDo, removeToDo } from './actions';
import store from './store';

class App extends Component {
    constructor() {
        super();
        this.state = {
            input: ""
        };
    }

    render() {
        <div>
            <ul>
                {this.props.todos.map(todo => {
                    return (
                        <li key={todo}>
                            <span>{todo}</span>
                            <button onClick={() => {this.props.dispatch(removeToDo(todo))}}>削除</button>
                        </li>
                    );
                })}
            </ul>

            <input type="text" onChange={e => this.setState({input: e.target.value})} />
            <button onClick={() => this.props.dispatch(addToDo(this.state.input))}>追加</button>
        </div>
    }
}

const mapStateToProps = state => {
    return {
        todos: state.todos.list
    }
};

export default connect(mapStateToProps)(App);
```

# まとめ
思ったより難しくなかったですよね:point_up:。
ただ、ReducerやStateの数が増えたりすると、そのたくさんあるReducer・Stateをどう分割していくかが難しかったりします。
この記事を参考にReduxの知識をつけてもらえますと幸いです。