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

  • 967
    いいね
  • 0
    コメント

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

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

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

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

スクリーンショット 2015-11-30 1.27.09.png

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

Action

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

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

ActionCreator

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

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

2. StoreへActionをdispatchする

スクリーンショット 2015-11-22 23.33.31.png

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

dispatch(addTodo(text))

Store

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

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

State

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

{
  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

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

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
Reducerの実装は、actionのtypeに応じて処理を書く事になります。

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

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
Reducerによって新しいStateが作成されるので、Storeは現在のStateに代わり保持します。

Reactとの連携

相関図のViewの部分がReactJSが担う部分となります。
実装については「Redux入門 6日目 ReduxとReactの連携」を参照してください。

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の基礎となります。詳しく掘り下げたい場合は以下の記事を参考にしてください。