我有一个 reducer 树,看起来像这样:
module.exports = combineReducers({
routing: routeReducer,
app: combineReducers({
setup: combineReducers({
sets,
boosters
}),
servers: combineReducers({
servers
})
})
});
现在,
setup
key 包含一个表单,一旦我们提交了该表单,就需要将其重置。但是,我无法访问整个setup
树,因为使用CombineReducers意味着reducer仅在树的叶子节点(在这种情况下为sets
和boosters
)上操纵数据。我的第一个冲动是制作一个减少整个安装树的函数,如下所示:
function setup(state, action){
//If there's an action that affects this whole tree, handle it
switch(action.type){
case "FORM_SUBMIT": //DO STUFF
break;
}
//Otherwise just let the reducers care about their own data
return combineReducers({
sets,
boosters
})(state);
}
但这是行不通的,而且还会弄乱我的第一个代码示例的漂亮树结构。
使用redux是否有更好的解决方案?
最佳答案
combineReducers
是一个很好的模式,因为它倾向于强制执行这样的想法,即reducer的作用域应该是商店的非重叠子集,并且应与商店本身的结构脱钩。它认为您应该减少叶子而不是分支,并且可以减少分支。
也就是说,使用替代模式可能有充分的理由。正如我在related question中提到的那样,您可以选择完全不使用combineReducers
并根据需要分解分解器。
在您的情况下,您可以装饰内部combineReducers
:
module.exports = combineReducers({
routing: routeReducer,
app: combineReducers({
setup: setupReducer(
combineReducers({
sets,
boosters
})
),
servers: combineReducers({
servers
})
})
});
在这里,
setupReducer
是higher-order function。这可能很难理解,但是这是我的处理方法:setupReducer
将reducer作为参数,因为我们正在将combineReducers
的结果传递给它。 combineReducers
返回的reducer的签名是(state, action) => state
。 setupReducer
必须返回一个reducer,它也是签名(state, action) => state
的函数。 换句话说,它需要一个缩减器,并返回一个缩减器:
((state, action) => state) => ((state, action) => state)
。所以它可能看起来像:function setupReducer(subReducer) {
return (state, action) => {
//If there's an action that affects this whole tree, handle it
switch(action.type){
case "FORM_SUBMIT":
// ... create newState
return newState;
default:
return subReducer(state, action);
}
}
}
我已将您的逻辑流程放在上面,但为慎重起见,您可能希望无条件调用
subReducer
,然后修改其输出。否则,必须确保未调用分支的对象始终产生相同形状的对象,这似乎是耦合的潜在粘性点。关于reactjs - 使用Redux CombineReducers减少整个子树,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34427851/