カスタムReduxの中のcombineReducers
4764 ワード
概要
Reduxの
This helper is just a conventience!You can write your own combineReducers that works differently,or even asemble the state object from the child reducers mandou and write a root reducing function explicity,like you would write function.
原理
まずreducerの書き方を思い出します.
実際には、このステップで
先ほどあなたを呼んだところを覚えていますか?そうです.これです.
しかし、上記の例では、cobineReducersの機能をシミュレートしましたが、cobineReducersの検査対象の変化の機能が失われました.今のdefault blockでは新たな対象に戻ります.cobineReducersの全部の機能を保留しながら拡張できる方法がありますか?実はとても簡単です.cobineReducersの戻りの関数を利用すればいいです.(liximomomomoさんが上記の例の欠陥を指摘してくれてありがとうございます)
Reduxの原則に従って、異なったreducerは互いに独立しなければならなくて、それらの間はいかなる依存があるべきでありません.この原則は見たところ美しいですが、実際に使うと例外があります.簡単な例として、私が経験した例です.簡単な表を実現することです.まず
この時、私達は自分達の需要を解決するためにカスタム
(終わり)
出典
http://scarletsky.github.io/2...
参考資料
http://redux.js.org/docs/api/...https://github.com/reactjs/re...
Reduxの
combineReducers
は、複数のreducersを容易に組み合わせて、新しいreducerにすることができます.しかし、私達のアプリケーションがますます複雑になるにつれて、combineReducers
は私達の需要を満たすことができないかもしれません.Redux公式文書によると、This helper is just a conventience!You can write your own combineReducers that works differently,or even asemble the state object from the child reducers mandou and write a root reducing function explicity,like you would write function.
combineReducers
は私たちが使うのに都合がいいだけです.私たちは完全に違ったcombineReducers
をカスタマイズして、私たちの特別な需要を満たすことができます.原理
まずreducerの書き方を思い出します.
const reducer = (oldState, action) => newState;
reducerは、通常の関数であり、2つのパラメータを受け入れる:oldState
およびaction
、そしてnewState
に戻る.複数のreducersを組み合わせるために、私達は通常Reduxが持参するcombineReducers
を使って実現します.const rootReducer = combineReducers({
key1: key1Reducer,
key2: key2Reducer
});
まず注意してください.私たちは何を伝えましたか?combineReducers
に渡します.{
key1: function(state.key1, action) { /*...*/ },
key2: function(state.key2, action) { /*...*/ },
}
はい、まず考えてみます.combineReducers
の処理を経て、私達は何を得ましたか?考えなくてもいいです.明らかに新しいreducerを得ました.この新しいレデューサーはどうですか?const rootReducer = (oldState, action) => newState;
驚くはずがないです.すべてのreducerがこのように成長しているので、たとえそれが既に組み合わされたreducerであっても、それはこのように長いです.今はcombineReducers
が何をしたかを当てるべきですよね?実は一番基本的な形態はこのようです.function combineReducers(reducers) {
return function (state, action) { /*...*/ };
}
これは、reducers
をパラメータとして受け入れ、標準のreducer関数を返す.実際には、このステップで
combineReducers
をカスタマイズすることができます.私たちは同じような関数を書くことができます.しかし、先にReduxが持っているswitch...case
が何をしたかを見たほうがいいと思います.私たちがカスタマイズしたcombineReducers
は元の機能が必要かもしれません.先ほどあなたを呼んだところを覚えていますか?そうです.これです.
// reducers
{
key1: function(state.key1, action) { /*...*/ },
key2: function(state.key2, action) { /*...*/ }
}
combineReducers
のプロセスを振り返ってみましょう.store.dispatch(action)
がトリガしたとき、すべてのreducersはこのaction
に応答して、対応する変化をして、最後に新しいaction
に戻ります.上記の構造に対して、私達は実はこのような効果を簡単に書き出すことができます.他の処理も加えられます.function reCombineReducers(reducers) {
return function (state, action) {
switch (action.type) {
case SP_ACTION:
return Object.assign({}, state, { /* do something */ });
default:
return Object.keys(reducers)
.map(k => ({ [k]: reducers[k](state[k], action) }))
.reduce((prev, next) => Object.assign({}, prev, next));
}
}
}
上記の例はもとのstore
の機能をシミュレートしました.combineReducers
に対して特殊な処理をしました.簡単でしょう.しかし、上記の例では、cobineReducersの機能をシミュレートしましたが、cobineReducersの検査対象の変化の機能が失われました.今のdefault blockでは新たな対象に戻ります.cobineReducersの全部の機能を保留しながら拡張できる方法がありますか?実はとても簡単です.cobineReducersの戻りの関数を利用すればいいです.(liximomomomoさんが上記の例の欠陥を指摘してくれてありがとうございます)
function reCombineReducers(reducers) {
let fn = combineReducers(reducers);
return function (state, action) {
switch (action.type) {
case SP_ACTION:
return Object.assign({}, state, { /* do something */ });
default:
return fn(state, action);
}
}
}
実例Reduxの原則に従って、異なったreducerは互いに独立しなければならなくて、それらの間はいかなる依存があるべきでありません.この原則は見たところ美しいですが、実際に使うと例外があります.簡単な例として、私が経験した例です.簡単な表を実現することです.まず
SP_ACTION
を設計します.// state
{
rows: { ... },
cells: { ... },
data: { ... }
}
state
、rows
、cells
は、いくつかの特定のdata
(例えば、action
、CHANGE_ROW_PROPS
、CHANGE_CELL_PROPS
)に応答して、それぞれの変化を作り出します.しかし、いくつかの特殊なaction(CHANGE_DATA
など、サービスからデータを取得することに成功したという意味)が発生した時、災難が発生しました.すべてのreducerはGET_TABLE_SUCCESS
のこのactionを傍受する必要があります.GET_TABLE_SUCCESS
、UPDATE_TABLE_SUCCESS
などのREMOVE_TABLE_SUCCESS
を追加すると、n個のファイルを再修正します.これは合理的ではありません.なぜ簡単な機能を加えて、こんなに多くの書類を修正する必要がありますか?この時、私達は自分達の需要を解決するためにカスタム
action
が必要です.function reCombineReducers(reducers) {
let fn = combineReducers(reducers);
return function (state, action) {
switch (action.type) {
case GET_TABLE_SUCCESS:
case UPDATE_TABLE_SUCCESS:
return Object.assign({}, state, action.payload.table);
case REMOVE_TABLE_SUCCESS:
return initState;
default:
return fn(state, action);
}
}
}
const table = reCombineReducers({
sections,
suites,
rows,
cells,
toys,
data,
logics
})
どうですか?複数のファイルを修正するよりずっと楽ですか?(終わり)
出典
http://scarletsky.github.io/2...
参考資料
http://redux.js.org/docs/api/...https://github.com/reactjs/re...