ReplaceReducer导致意外的密钥错误 [英] ReplaceReducer causing unexpected key error

查看:136
本文介绍了ReplaceReducer导致意外的密钥错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动态加载模块的React应用程序,包括模块的reducer函数,然后调用Redux的replaceReducer来替换reducer。不幸的是我收到错误

I have a React app that dynamically loads a module, including the module's reducer function, and then calls Redux's replaceReducer to, well, replace the reducer. Unfortunately I'm getting an error of


在传递给createStore的initialState参数中找到意外的键bookEntry。预计会找到一个已知的reducer键:bookList,root。意外的密钥将被忽略。

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 是旧版reducer上的一个关键字。从bookEntry模块开始并切换到bookList会导致此反向错误

where bookEntry was a key on the older reducer that's getting replaced. And starting with the bookEntry module and switching to bookList causes this inverse error


在传递给createStore的initialState参数中找到意外的键bookList。预计会找到一个已知的reducer密钥:bookEntry,root。意外的密钥将被忽略。

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.

代码如下 - 取消注释评论代码确实解决了这个问题,但我是猜测它不应该是必需的。

The code is below - un-commenting the commented code does in fact fix this, but I'm guessing it shouldn't be needed.

我在做Redux的其他问题是否需要这些代码?

Am I doing something else wrong with Redux that's making this code necessary?

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
    }));
}


推荐答案

一般来说我们建议您在更改路径或加载新模块时清理数据。这会使应用程序的可预测性降低一些。如果我们谈论数十万的记录,那么肯定。这是您计划加载的数据量吗?

In general we don’t suggest you to "clean up" the data when changing routes or loading new modules. This makes the application a little less predictable. If we’re talking about hundreds of thousands of records, then sure. Is this the volume of the data you plan to load?

如果每个页面上只有几千个项目,那么卸载它们没有任何好处,那里与您添加到应用程序的复杂性相关的缺点。因此,请确保您正在解决一个真正的问题,而不是过早地进行优化。

If there’s just a couple of thousands of items on every page, there is no benefit to unloading them, and there are downsides associated with the complexity you add to the application. So make sure you’re solving a real problem, and not optimizing prematurely.

现在,来警告消息。检查在 combineReducers()中定义。这意味着将丢弃意外的状态键。删除管理 state.bookEntry bookEntry reducer后,新部分不再识别该部分状态root reducer和 combineReducers()记录了一条警告,它将被丢弃。 请注意,这是一个警告,而不是错误。您的代码运行正常。我们使用 console.error()来突出显示警告,但它实际上没有抛出,所以你可以放心地忽略它。

Now, to the warning message. The check is defined inside combineReducers(). It means that unexpected state keys will be discarded. After you removed the bookEntry reducer that managed state.bookEntry, that part of the state was no longer recognized by the new root reducer, and combineReducers() logged a warning that it’s going to be discarded. Note that this is a warning, and not an error. Your code runs just fine. We use console.error() to make warning prominent, but it didn’t actually throw, so you can safely ignore it.

我们真的不希望警告可配置,因为你基本上隐式删除部分应用程序状态。通常人们会误做,而不是故意这样做。所以我们想对此发出警告。如果您想绕过警告,最好的办法是手动编写根减速器(目前由 combineReducers()生成)。它看起来像这样:

We don’t really want to make the warning configurable because you’re essentially implicitly deleting part of the application state. Usually people do this by mistake, and not intentionally. So we want to warn about that. If you want to get around the warning, your best bet is to write the root reducer (currently generated by combineReducers()) by hand. It would look like this:

// 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));
}

但我们推荐的模式是保持旧的减速器

这篇关于ReplaceReducer导致意外的密钥错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆