LoginSignup
28
27

More than 5 years have passed since last update.

Redux の reducer で switch を使わない

Last updated at Posted at 2016-08-06

はじめに

下記のコードは、公式ドキュメントのコピペです。テクニックについてとても勉強になったので感想を入れつつ、メモを残しています。

Switchによる問題点と関数型プログラミングのアプローチ

Switchによる制御は、分岐が増えることによって制御を行うプログラムの実装が複雑になっていく可能性がある。
例えばReduxにおける、Reducerの実装がそれにあたる。

今後ActionTypeがどんどん増えていくと、`todos`の実装は長くなり、Switch分の中身が複雑になっていく
export function todos(state = [], action) {
  switch (action.type) {
  case ActionTypes.ADD_TODO:
    let text = action.text.trim()
    return [ ...state, text ]
  default:
    return state
  }
}

関数型プログラミング脳では、このような問題に関して、扱う範囲を分解することでそれぞれをシンプル作れないか?という疑問をいつも持つことが推奨されている。
そこで今回のケースでは、ある特定の条件に基づいて、それぞれの場合に応じた具体的な処理を決定し実行するという問題を、

  • 任意の条件にマッチしたら対応する関数を呼び出す(という抽象的な問題)
  • 特定の条件と具体的な処理を実装し、上の関数に登録する(という具体的な問題)

という二つに分解する。

`todoReducer`内の実装で特定の条件と具体的な処理のペアが増えても、`createReducer`の実装は変わらない
const ActionType = {
  ADD_TODO: 'ADD_TODO',
  TOGGLE_TODO: 'TOGGLE_TODO'
}

// 任意の条件にマッチしたら対応する関数を呼び出す
function createReducer (initialState, handlers) {
  return function reducer(state = initialState, action) {
    if (handlers.hasOwnProperty(action.type)) {
      return handlers[action.type](state, action);
    } else {
      return state;
    }
  }
}

// 特定の条件と具体的な処理を実装し、上の関数に登録する
const todoReducer = createReducer([], {
  [ActionType.ADD_TODO] (state, action) {
    const text = action.text.trim();
    return [...state, text];
  }
});

こうすることでActionTypeの種類が増えて実装を修正するときにも、createReducerのテストケースを増やす必要はない。またtodoReducerの実装もプロパティにActionCreatorを追加するだけでSwitch文などの制御自体をを増やす必要はない。さらに、createReducerはどのプロジェクトにも再利用することができる。

(実装を追加しても、複雑さを増やさないという意味で)うん、エレガント

28
27
0

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
28
27