redux の repatch middleware を実装しようとしたメモ
色々コンテキスト略。自分用の作業メモ。
jaystack/repatch を redux の middleware に移植しようとしたが、いくつか問題があった。
- ActionCreator が reducer を返す、という基本コンセプトを維持するとする
- しかし repatch はストアがシングルトン前提なので、そのまま移植すると combineReducers で破綻する
- ので reducer関数の参照を action.type として使って、reducer を当てる対象としてスコープをコントロールできるのでは
- というのを考えたが、dispatch 時にreducer参照が必要になってしまい、どう考えてもAPIがきれいにならない
- よく考えたら、 connect の第二引数で bindActionCreators する時にdispatchと関数一覧を渡してどうにか出来るのでは?
- ということで * as actions するとして、 規約 で default を reducer、残りを ActionCreator と決め打ってしまうと綺麗になるかもしれない
練った結果、こういうのが作れるのがわかった
// reducers/index.js import { combineReducers } from 'redux' import counter from './counter' export default combineReducers({counter}) // reducers/counter.js import { createReducer } from 'apatcher-redux' export type Counter = { value: number } export const addAsync = (n: number) => async (state: Counter) => ({ value: state.value + n }) export default createReducer({ value: 0 }) // containers/Counter.js import * as counter from '../reducers/counter' import * as foo from '../reducers/foo' import { bindReducersToActions } from 'apatcher-redux' connect( (state: Counter) => state, bindReducersToActions({counter, foo}) )(function A(props) { return ( <div> <button onClick={() => props.counter.addAsync(1)}>Add 1</button> <button onClick={() => props.counter.addAsync(2)}>Add 2</button> </div> ) })
問題はあって
- 暗に default が reducer としてたり、ファイルスコープに規約を持ち込んでしまってるのがあまりよくなさそう
- connect 側から見てactionsに異常に型が付けづらい
- テスト時に専用のコンテキストを組み立てる手間が多くて面倒
- reduxに対して部分的に使えるようにしたところで、パラダイムが違いすぎて混ぜるのは見通しがすごく悪い
これ実装したところで生の redux 使うのとどっちが楽かというところで、結局強いメリットを示せないのではないか、という結論になって一晩寝かせて考えたほうが良さそう。