moxt

Just another Blog site

ReduxのcombineReducersの仕組みについて理解したいマン

   

Redux

Reduxでは、関心毎に複数のReducerを作っておきcombineReducersで1つのReducerにまとめた後createStoreする、という風習がある。
combineReducersがどのようにして複数のReducerをまとめ上げるのか気になったのでコード読んで、過程をメモしてった。

結果、スゴい冗長な感想文になった。。

combineReducersの全貌

短いね。

pick

まずここ。

pickという関数で絞り込みっぽいことをしてる。
pickはReduxが用意してるユーティリティ。

オブジェクトから条件に当てはまるモノだけをピックアップした新たなオブジェクトを返す関数。
細かく見ると、オブジェクトのキーを総なめしつつ、対応する値を条件式(引数で与えられたfn)に突っ込んで真であればresultオブジェクトにキーと値セットで追加してる。
ちなみにkeyはReducerの名前でvalが関数オブジェクトとなってる。

与えられたReducer群から不純物(関数じゃないReducer → typeof val === ‘function’)を取り除いてる。

pickの実行例

assertReducerSanity

pickによって選ばれたReducersがReducerとしての要件を満たしてるか確認する処理。
ここのコードはシンプル。

まず、Reduxでは原則としてReducerに対して何かしらのActionを与えると、何かしらのオブジェクト(各Reducerの初期状態State)が返ってくることを期待してる。
なのでActionTypes.INITを投げてundefinedが返ってきたときはエラーを投げてる。
また、適当なActionを投げられたときもオブジェクトを返ってくることを期待してる。
ActionType.INITではオブジェクトを返すがまったくのデタラメなActionの場合はundefinedではダメなのだ。

combination(state = {}, action)

先ほどのサニタイズを通過するとcombinationという関数を返す。
これはpickで選別されたfinalReducersを抱えたReducerである。

getUnexpectedStateShapeWarningMessage

ここはプロダクション時にはチェックしないので省略。
Reducerが1つもなかったり、stateがプレーンオブジェクトじゃないと怒られたりする。

mapValues

最後にパッと見、ウッとなる処理が出てくる。

が、やってることはシンプルでfinalReducersに対して総当りでreduce()して最終的なstateを返してる
で、何かしらstateに変更があればfinalStateを、何も変更がなければ与えられたstateを返す。

mapValuesってのが要で、これは先ほどのpickと同じくReduxのユーティリティ。

あるオブジェクトobjのval(obj[key])とkeyをfnに与えた結果をvalに設定したオブジェクトを生成してる。

実際にmapValuesに突っ込んでるのはそれぞれ…

objが

fnが

と、なってる。

finalReducersにはkeyがReducer名でvalが関数のオブジェクトがひしめいている。

あるオブジェクトobjのval(=obj[key])とkeyをfnに与えた結果をvalとするオブジェクトを生成してる。

なので
あるオブジェクト{ ‘awesomeReducer’: (state={}, action)=>{ /* awesome… */} }の
valの『(state={}, action)=>{…}』とkeyの『’awesomeReducer’』をfnに与えた結果をvalとするオブジェクトを生成してる。

fnの中を見てみよう。

Reducer名に対応するstateを取得してる。
これはpreviousStateForKeyという名前の通りreducerを実行する前のStateで、これはreducer後のStateを比較するために使う。

例でいうところの’awesomeReducer’に対応するreducerを実行して、その結果をnextStateForKeyに格納してる。

reducer後の結果がundefinedになるのはダメだからね。。

新旧のStateを比較して変化があるかチェックしてフラグ設定してる。
このhasChangedはcombinationの返り値でどのStateを返すか判別するために使う。

reducer後のStateを返して、keyに対する新しいvalとして追加してる。
mapValuesと合わせて見てると分かるかと思う。

で、これがReducer毎に実行された後に新しいオブジェクトfinalStateが完成する。
最後にhasChangedの状態に応じて適切なStateを返す。

これで終わり。

ここまでダラダラ冗長と書いてきたけどcombineReducersは、単に複数のReducerをループさせながら各Reducerを実行した結果を集約して返してるってだけ。

 - javascript

336px




336px




  • このエントリーをはてなブックマークに追加
  • follow us in feedly

  関連記事