Redux入門【ダイジェスト版】10分で理解するReduxの基礎

ReduxのGithubドキュメントを基に入門用記事として書いたものを、簡潔にまとめました。
もと記事はこちらです。

* [Redux入門 1日目 Reduxとは](http://qiita.com/kiita312/items/b001839150ab04a6a427)
* [Redux入門 2日目 Reduxの基本・Actions](http://qiita.com/kiita312/items/8f8d047e5cbd87399ccb)
* [Redux入門 3日目 Reduxの基本・Reducers](http://qiita.com/kiita312/items/7fdce94912d6d9c801f8)
* [Redux入門 4日目 Reduxの基本・Stores](http://qiita.com/kiita312/items/377787c24efac64f2495)
* [Redux入門 5日目 Reduxの基本・Data Flow](http://qiita.com/kiita312/items/ae3ce31521ad24dd699f)
* [Redux入門 6日目 ReduxとReactの連携](http://qiita.com/kiita312/items/d769c85f446994349b52)

## Reduxとは
Reduxは、ReactJSが扱うUIのstate(状態)を管理をするためのフレームワークです。Reactではstateの管理するデータフローにFluxを提案していますが、ReduxはFluxの概念を拡張してより扱いやすく設計されています。
Reduxはstateを管理するためのライブラリーなので、React以外にもAngularJSやjQueryなどと併せて使用することもできますが、Reactと使用するのが一番相性がいいです。

## Reduxの要素
Reduxの要素と、それらの相関図です。

* Action
* ActionCreator
* Store
* State
* Reducer

![スクリーンショット 2015-11-30 1.13.59.png](https://qiita-image-store.s3.amazonaws.com/0/36813/7402c7f4-a7b2-d4a2-e30d-d4ab5816487c.png "スクリーンショット 2015-11-30 1.13.59.png")

Todoアプリを例にしてReduxのデータフローをたどりながら、これらの要素を説明していきます。

###1. ユーザーの入力から、アクションを作成する

![スクリーンショット 2015-11-30 1.27.09.png](https://qiita-image-store.s3.amazonaws.com/0/36813/064f669a-d4d0-1842-c883-b6ac0b8b9b72.png "スクリーンショット 2015-11-30 1.27.09.png")

ユーザーがtodoのテキストを入力して追加ボタンを押した場合を想定します。
ActionCreatorのメソッドに入力内容が渡されて、Actionのオブジェクトを作成されます。

## Action

Actionは「何をする」という情報を持ったオブジェクトです。Actionはtypeプロパティを必ず持つ必要があります。

```js
{
  type: 'ADD_TODO',
  text: 'Build my first Redux app'
}
```

## ActionCreator

ActionCreatorはActionを作成するメソッドです。
FluxのActionCreatorとは違い、Actionを作るのみを行いStoreへのdispatchは行ないません。

```js
function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}
```

### 2. StoreへActionをdispatchする

![スクリーンショット 2015-11-22 23.33.31.png](https://qiita-image-store.s3.amazonaws.com/0/36813/619bbcf4-6c98-49f6-fca6-fb0db8efa93e.png "スクリーンショット 2015-11-22 23.33.31.png")

ActionCreatorで生成されたActionをStoreに送ります。
Storeのインスタンスにdispatch(action)を行なう事でStoreへ変更を伝えます。

```js
dispatch(addTodo(text))
```

## Store
Storeはアプリケーションの状態(state)を保持している場所です。
Storeはアプリケーション内で一つ存在し、一つのstateを保持しています。
Storesの役割は、

* stateを保持する
* stateへアクセスするためのgetState()を提供する
* stateを更新するためのdispatch(action)を提供する
* リスナーを登録するためのsubscribe(listener)を提供する

## State
アプリケーションでの状態を表します。
このTodoアプリでは「現在選択されている表示/非表示」、「todoのリスト」をstateとして保持します。
より内容が複雑になる場合は、ネストしたツリー状の構造で表します。

```js
{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}
```

###3. dispatchされたactionとstateをReducerへ渡す
![スクリーンショット 2015-12-04 3.06.44.png](https://qiita-image-store.s3.amazonaws.com/0/36813/9107a02d-43aa-823f-c636-0de88ec307cc.png "スクリーンショット 2015-12-04 3.06.44.png")

Storeは、Storeを作成する際にStateを変更するためのメソッドであるReducerを一つ登録します。
Storeはdispatchされると、引数のactionと現在保持しているStateをReducerへ渡し、新しいStateを作成します。


```js
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
```

## Reducer
reducerはactionとstateから、新しいstateを作成して返すメソッドです。ポイントは、引数のstateを更新することはせず、新しいstateのオブジェクトを作成して返します。
reducerのメソッドは副作用を起こさないpureな関数でなければならず、Aというstateに対して毎回必ずBというstateを返すような関数でなければなりません。

![スクリーンショット 2015-11-22 23.33.49.png](https://qiita-image-store.s3.amazonaws.com/0/36813/0f880b89-450a-12aa-d676-7a0407f49506.png "スクリーンショット 2015-11-22 23.33.49.png")
Reducerの実装は、actionのtypeに応じて処理を書く事になります。

```js
function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    case COMPLETE_TODO:
      return Object.assign({}, state, {
        todos: [
        ...state.todos.slice(0, action.index),
        Object.assign({}, state.todos[action.index],{
        completed: true
      }),
      ...state.todos.slice(action.index + 1)
    ]
  }) 
    default:
      return state
  }
}
```

Reducerはアプリケーションが大きくなるにつれて実装が肥大化してしまうので、Reducer内に子Reducerを作成し、stateのプロパティごとに子Reducerで処理するようにします。
![スクリーンショット 2015-11-22 23.34.10.png](https://qiita-image-store.s3.amazonaws.com/0/36813/09b962f8-676c-d004-2f84-21f76b327398.png "スクリーンショット 2015-11-22 23.34.10.png")

```js
function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case COMPLETE_TODO:
      return [
        ...state.slice(0, action.index),
        Object.assign({}, state[action.index], {
          completed: true
        }),
        ...state.slice(action.index + 1)
      ]
    default:
      return state
  }
}

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

function todoApp(state = {}, action) {
  return {
    visibilityFilter: visibilityFilter(state.visibilityFilter, action),
    todos: todos(state.todos, action)
  }
}
```

###4. Reducerが作成した新しいstateをstoreが保存する
![スクリーンショット 2015-12-05 0.50.34.png](https://qiita-image-store.s3.amazonaws.com/0/36813/9ebc522f-7195-8a0e-be9e-123c772c323d.png "スクリーンショット 2015-12-05 0.50.34.png")
Reducerによって新しいStateが作成されるので、Storeは現在のStateに代わり保持します。

## Reactとの連携
相関図のViewの部分がReactJSが担う部分となります。
実装については「[Redux入門 6日目 ReduxとReactの連携](http://qiita.com/kiita312/items/d769c85f446994349b52)」を参照してください。

##Reduxの3原則

最後になりますが、Reduxの基本設計は以下の3つの原則に基づいて設計されています。
上記のデータフローはこの原則に則っていることがよく分かると思います。

###1. Single source of truth
アプリケーション内でStoreは1つのみとし、Stateは単独のオブジェクトとしてStoreに保持される。

### 2. State is read-only
Stateを直接変更することはできず、actionをStoreへdispatchすることでしかStateは変更できない。

### 3. Mutations are written as pure functions
Stateを変更する関数(Reducer)はpureな関数にする。

##最後に
以上がReduxの基礎となります。詳しく掘り下げたい場合は以下の記事を参考にしてください。

* [Redux入門 1日目 Reduxとは](http://qiita.com/kiita312/items/b001839150ab04a6a427)
* [Redux入門 2日目 Reduxの基本・Actions](http://qiita.com/kiita312/items/8f8d047e5cbd87399ccb)
* [Redux入門 3日目 Reduxの基本・Reducers](http://qiita.com/kiita312/items/7fdce94912d6d9c801f8)
* [Redux入門 4日目 Reduxの基本・Stores](http://qiita.com/kiita312/items/377787c24efac64f2495)
* [Redux入門 5日目 Reduxの基本・Data Flow](http://qiita.com/kiita312/items/ae3ce31521ad24dd699f)
* [Redux入門 6日目 ReduxとReactの連携](http://qiita.com/kiita312/items/d769c85f446994349b52)

2018/4/25 追記
React本体が提供するReduxライクな機能であるContextAPIについて書きました。
* [ReactのContext APIはReduxの代わりとなるのか]
(https://qiita.com/kiita312/items/8da6b429949a36ee2420)