ReplaceReducer 导致意外的键错误
ReplaceReducer causing unexpected key error
我有一个动态加载模块的 React 应用程序,包括模块的 reducer 函数,然后调用 Redux 的 replaceReducer 来替换 reducer。不幸的是,我收到
的错误
Unexpected key "bookEntry" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "bookList", "root". Unexpected keys will be ignored.
其中 bookEntry 是 正在更换的旧减速器上的键。从 bookEntry 模块开始并切换到 bookList 会导致此反向错误
Unexpected key "bookList" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "bookEntry", "root". Unexpected keys will be ignored.
代码在下面 - 取消注释注释代码实际上解决了这个问题,但我猜不应该需要它。
我是不是在 Redux 上做错了什么使得这段代码成为必要?
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
}));
}
一般来说我们不建议您在更改路由或加载新模块时“清理”数据。这使得应用程序有点不可预测。如果我们谈论的是 数十万 条记录,那当然可以。这是您计划加载的数据量吗?
如果每个页面上只有几千个项目,卸载它们没有任何好处,而且会增加应用程序的复杂性带来不利影响。因此,请确保您正在解决一个真正的问题,而不是过早地优化。
现在,转到警告消息。检查在 combineReducers()
内定义。这意味着意外的状态密钥将被丢弃。删除管理 state.bookEntry
的 bookEntry
reducer 后,新的根 reducer 不再识别那部分状态,并且 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));
}
但是我们推荐的模式是。
我有一个动态加载模块的 React 应用程序,包括模块的 reducer 函数,然后调用 Redux 的 replaceReducer 来替换 reducer。不幸的是,我收到
的错误Unexpected key "bookEntry" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "bookList", "root". Unexpected keys will be ignored.
其中 bookEntry 是 正在更换的旧减速器上的键。从 bookEntry 模块开始并切换到 bookList 会导致此反向错误
Unexpected key "bookList" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "bookEntry", "root". Unexpected keys will be ignored.
代码在下面 - 取消注释注释代码实际上解决了这个问题,但我猜不应该需要它。
我是不是在 Redux 上做错了什么使得这段代码成为必要?
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
}));
}
一般来说我们不建议您在更改路由或加载新模块时“清理”数据。这使得应用程序有点不可预测。如果我们谈论的是 数十万 条记录,那当然可以。这是您计划加载的数据量吗?
如果每个页面上只有几千个项目,卸载它们没有任何好处,而且会增加应用程序的复杂性带来不利影响。因此,请确保您正在解决一个真正的问题,而不是过早地优化。
现在,转到警告消息。检查在 combineReducers()
内定义。这意味着意外的状态密钥将被丢弃。删除管理 state.bookEntry
的 bookEntry
reducer 后,新的根 reducer 不再识别那部分状态,并且 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));
}
但是我们推荐的模式是