Javascript ReplaceReducer导致意外的密钥错误
我有一个React应用程序,它动态加载模块,包括模块的reducer函数,然后调用Redux的replaceReducer来替换reducer。不幸的是,我得到了一个错误 在传递给createStore的initialState参数中找到意外键“bookEntry”。希望找到一个已知的reducer键:“bookList”、“root”。意外的键将被忽略 其中bookEntry是正在更换的旧减速器上的一个键。从bookEntry模块开始切换到bookList会导致此反向错误 在传递给createStore的initialState参数中找到意外键“bookList”。希望找到一个已知的reducer键:“bookEntry”、“root”。意外的键将被忽略 下面是代码-取消注释注释的代码实际上解决了这个问题,但我猜不需要这样做 我是否对Redux做了其他错误,这使得这段代码成为必要Javascript ReplaceReducer导致意外的密钥错误,javascript,reactjs,redux,Javascript,Reactjs,Redux,我有一个React应用程序,它动态加载模块,包括模块的reducer函数,然后调用Redux的replaceReducer来替换reducer。不幸的是,我得到了一个错误 在传递给createStore的initialState参数中找到意外键“bookEntry”。希望找到一个已知的reducer键:“bookList”、“root”。意外的键将被忽略 其中bookEntry是正在更换的旧减速器上的一个键。从bookEntry模块开始切换到bookList会导致此反向错误 在传递给create
function getNewReducer(reducerObj){
if (!reducerObj) return Redux.combineReducers({ root: rootReducer });
//store.replaceReducer(function(){
// return {
// root: rootReducer()
// }
//});
store.replaceReducer(Redux.combineReducers({
[reducerObj.name]: reducerObj.reducer,
root: rootReducer
}));
}
通常我们不建议您在更改路由或加载新模块时“清理”数据。这会使应用程序的可预测性降低。如果我们说的是数十万条记录,那当然。这是您计划加载的数据量吗
如果每个页面上只有几千个条目,卸载它们没有任何好处,并且与您添加到应用程序中的复杂性相关的缺点也存在。因此,请确保您正在解决一个真正的问题,而不是过早地进行优化
现在,请看警告消息。该检查在组合减速机()
中定义。这意味着意外的状态键将被丢弃。删除管理状态.bookEntry
的bookEntry
还原程序后,新根还原程序不再识别该部分状态,并且combineReducers()
记录了一条警告,表示将丢弃该部分状态请注意,这是一个警告,而不是错误。您的代码运行正常。我们使用console.error()
来突出警告,但它实际上并没有抛出,所以您可以安全地忽略它
我们并不想让警告可配置,因为您实际上是在隐式删除应用程序状态的一部分。通常人们这样做是错误的,而不是故意的。因此,我们想对此提出警告。如果您想避开警告,最好是手动编写根减速机(当前由combineReducers()
生成)。它看起来是这样的:
// I renamed what you called "root" reducer
// to "main" reducer because the root reducer
// is the combined one.
let mainReducer = (state, action) => ...
// This is like your own combineReducers() with custom behavior
function getRootReducer(dynamicReducer) {
// Creates a reducer from the main and a dynamic reducer
return function (state, action) {
// Calculate main state
let nextState = {
main: mainReducer(state.main, action)
};
// If specified, calculate dynamic reducer state
if (dynamicReducer) {
nextState[dynamicReducer.name] = dynamicReducer.reducer(
nextState[dynamicReducer.name],
action
);
}
return nextState;
};
}
// Create the store without a dynamic reducer
export function createStoreWithoutDynamicReducer() {
return Redux.createStore(getRootReducer());
}
// Later call this to replace the dynamic reducer on a store instance
export function setDynamicReducer(store, dynamicReducer) {
store.replaceReducer(getRootReducer(dynamicReducer));
}
但是,我们推荐的模式是。在动态加载代码时,是否有任何特定的原因要删除以前的减速器?我不太明白。一般来说,你希望旧的减速器留下来,而不是被移除。@DanAbramov-hm,没有具体的原因。我只是假设即将推出的模块会自行“清理”。这不是我在实践中应该做的吗?我是否应该发出一个调度以清除其数据,但离开减速机?什么是“清理”的目的?通常情况下,您只需保留数据,以防用户返回此页面。@DanAbramov在尝试诸如React之类的新事物时,我通常会尝试模拟一些大的东西,比如在我的9-5工作中,这样我就可以看到如何在“现实生活”(与ToDo相反)中使用它。如果我们把一切都放在身边,从日程安排、账单、联系人管理、任务、文件等等,事情会很快失控。对于我习惯使用的应用程序类型来说,清除掉一个必要的条件——如果你好奇的话(令人困惑的是,为什么面向公众的网站没有应用程序的屏幕截图——它非常清晰)谢谢丹-根据法律,我必须再等17个小时才能获得赏金:)非常感谢你提供的信息。我战斗的日子早已过去;我很乐意离开旧的缩减器,如果实际需要的话,简单地清除多余的数据。你有没有可能找到把这些信息输入文档的方法?这几乎是redux中唯一一个文档有点有限的部分。@Adam我现在根本没有时间为文档做贡献。需要一个全面的“动态代码加载”方法,但有人需要拥有它,而我不能。不用担心。您为开发人员社区做了很多工作。在我花更多的时间在replaceReducer上更新一些文档,以便更好地理解事情之后,你会接受一份带有更新文档的PR吗?@Adam是的,但我们尽量保持API文档简洁。配方应该是更正确的形式。