Redux は 概念的に Rx のサブセットであるという話
この資料のアレ。
Reducer は単なる (State, Action) => State
の関数で、redux.combineReducers は複数の reducer を名前空間でマップした新しい reducer にするもの。
Rx分かる人、Redux分かる人向けに、 redux.combineReducers を実装して、Rx.Observable.scan で reducer として実際に動くコードを書いた。
const Rx = require('rx') const combineReducers = reducerMap => { const initialState = Object.entries( reducerMap ).reduce((acc, [key, reducer]) => { return Object.assign({}, acc, { [key]: reducer(undefined, { type: '__init' }) }) }, {}) return (state = initialState, action) => { console.log('run combined reducer') return Object.entries(reducerMap).reduce((acc, [key, reducer]) => { return Object.assign({}, acc, { [key]: reducer(state[key], action) }) }, {}) } } const ADD = 'add' const add = n => ({ type: ADD, payload: n }) const initialState = { value: 0 } const counter = (state = initialState, action) => { switch (action.type) { case ADD: return { value: action.payload + state.value } default: return state } } const rootReducer = combineReducers({ counter }) const actions = Rx.Observable.from([add(1), add(2), add(3)]) const scanned = actions.scan(rootReducer, undefined) // need undefined to pass with reducer on init scanned.subscribe(x => { console.log('subscribe', x) })
最後の subscribe の console の代わりに ReactDOM.render にすれば、純粋関数な React Component が render できて、それをHoCとしてラップしてるのが ReactRedux.Provider というわけ。
Rx は 直接 Event Stream (Observale, Action Stream) を扱うけど、Redux は1つのEventを手がかりに前後の状態だけを記述するので、扱うスコープを限定したRx とも言える。スナップショットを確定するために 2つ以上または時系列的に差がある Stream 中の Event を使わないといけない場合、 Redux Middleware が出てくるけど、これをシュッと綺麗に書けるのは Rx の方。ただほとんどのケースでReduxのスコープの狭め方は有用。