3109
2906

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-12-04

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

2018/4/25 追記
React本体が提供するReduxライクな機能であるContextAPIについて書きました。

3109
2906
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3109
2906

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?