Skip to content

Latest commit

 

History

History
 
 

10-immutable-redux-improvements

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

10 - Immutable JSとReduxの改良

Immutable JS

前章とは違い、本章はとても簡単で、ちょっとした変更を行うだけです。

まず、コードベースにImmutable JSを追加します。Immutableはオブジェクトを変更(mutating)することなしに扱うためのライブラリです。例えば以下のようにする代わりに:

const obj = { a: 1 };
obj.a = 2; // Mutates `obj`

こうすることができます:

const obj = Immutable.Map({ a: 1 });
obj.set('a', 2); // Returns a new object without mutating `obj`

このアプローチは関数型プログラミングのパラダイムに則ったもので、Reduxとの相性がとても良くなっています。実際、reducer関数は引数として渡される状態を変更しない、純粋な関数でなければならず、状態オブジェクトを新しく作って返すようになっています。それではImmutableを使い、このやり方を強制してみましょう。

  • yarn add immutableを実行します。

このコードベースではMapを使うのですが、ESLintとAirbnbの設定はクラス以外に大文字の名前を使うと警告を出します。package.jsoneslintConfigに以下を追加します:

"rules": {
  "new-cap": [
    2,
    {
      "capIsNewExceptions": [
        "Map",
        "List"
      ]
    }
  ]
}

これはMapList(この2つのImmutableなオブジェクトはずっと使うことになります)を例外扱いするようESLintルールを変更するものです。この冗長なJSONフォーマットはYarn/NPMによって自動的に行われるもので、残念ながらコンパクトにはできません。

それはさておき、Immutableに戻りましょう:

dog-reducer.jsを以下のように修正します:

import Immutable from 'immutable';
import { MAKE_BARK } from '../actions/dog-actions';

const initialState = Immutable.Map({
  hasBarked: false,
});

const dogReducer = (state = initialState, action) => {
  switch (action.type) {
    case MAKE_BARK:
      return state.set('hasBarked', action.payload);
    default:
      return state;
  }
};

export default dogReducer;

初期状態はImmutableのMapを使って作られます。そして新しい状態は、それ以前の状態を変更することのないset()を使って作られるようになります。

containers/bark-message.jsmapStateToProps関数を、.hasBarkedの代わりに.get('hasBarked')を使うよう修正します:

const mapStateToProps = state => ({
  message: state.dog.get('hasBarked') ? 'The dog barked' : 'The dog did not bark',
});

アプリケーションは以前と同様の振る舞いをするはずです。

注意: BabelがImmutableについて100KB制限を超えていると警告する場合, package.jsonbabelのところに"compact": falseを追加します。

上記のコード片を見ると分かる通り、状態オブジェクトは素のオブジェクト属性dogを持っており、イミュータブルではありません。これはこれで構わないのですが、イミュータブルオブジェクトしか扱いたくない場合、ReduxのcombineReducers関数を置き換えるため、redux-immutableパッケージをインストールできます。

オプション:

  • yarn add redux-immutableを実行します。
  • app.jsxにあるcombineReducers関数をredux-immutableからimportしたものに置き換えます。
  • bark-message.jsstate.dog.get('hasBarked')state.getIn(['dog', 'hasBarked'])に置き換えます。

Reduxアクション

アプリにアクションを加えていくにつれて、同じボイラープレートを何度も書き加えていくことになります。redux-actionsパッケージを使えば、ボイラープレートのコードを減らしてくれます。dog-actions.jsファイルをredux-actionsで簡潔に書き換えることができます。

import { createAction } from 'redux-actions';

export const MAKE_BARK = 'MAKE_BARK';
export const makeBark = createAction(MAKE_BARK, () => true);

redux-actionsは先ほど実装したようなアクションであるFlux Standard Actionモデルを実装したもので、このモデルに従っていればredux-actionsはシームレスに導入できます。

  • yarn add redux-actionsを忘れずに実行します。

(原文: 10 - Immutable JS and Redux Improvements)

次章: 11 - Mocha、Chai、Sinonによるテスティング

前章 または 目次に戻る。