Redux:在传递给 createStore 的 preloadedState 参数中发现意外的键

IT技术 javascript reactjs redux
2021-05-24 11:43:50

你能帮我例外吗 Unexpected key "userName" found in preloadedState argument passed to createStore. Expected to find one of the known reducer keys instead: "default". Unexpected keys will be ignored.

我发现了这个链接,但它对我没有帮助。我不理解某些东西,也许这部分来自文档:与传递给它的键具有相同形状的普通对象

你能在我的例子中解释我的错误吗?

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import  App from './containers/App.jsx';
import * as reducers from './reducers'
import types from './constants/actions';

const reducer = combineReducers(reducers);

const destination = document.querySelector("#container");

var store = createStore(reducer, {
    userName : ''
});


ReactDOM.render(
    <Provider store={store}>
        <App/>
    </Provider>,
    destination
);

console.log(1)

store.subscribe( ()=> {
console.log("-------------------------")
let s = store.getState()
console.log("STATE = " + s)
for (var k in s) {
    if (s.hasOwnProperty(k)) {
        console.log("k = " + k + "; value = " + s[k]);
    }
}
})

store.dispatch({
        type: types.LOAD_USER_NAME,
        userName : "Oppps1"
})

我的减速机:

import types from './../constants/actions'

export default function userNameReducer (state = {userName : 'N/A'}, action) {
console.log('inside reducer');
switch (action.type) {
    case types.LOAD_USER_NAME:
        console.log("!!!!!!!!!!!!!!!")
        console.log("action.userName = " + action.userName)
        for (var k in state) {
            if (state.hasOwnProperty(k)) {
                console.log("k = " + k + "; value = " + state[k]);
            }
        }
        return action.userName;
    default:
        return state
}
}

执行后结果在控制台:

在此处输入图片说明

3个回答

TLDR:停止使用combineReducerscreateStore直接将您的减速器传递给使用import reducer from './foo'代替import * from './foo'

默认导入/导出的示例,没有combineReducers

// foo.js
function reducer(state, action) { return state; }
export default reducer;

----

// index.js
import myReducer from './foo';

示例与 combineReducers

// foo.js
export default (state, action) => { ... }

----

// bar.js
export default (state, action) => { ... } 

----

// index.js
import foo from './foo';
import bar from './bar';

const store = createStore(combineReducers({
    foo,
    bar,
});

createStore(preloaded state)的第二个参数必须与组合的减速器具有相同的对象结构。combineReducers获取一个对象,并将对象中提供的每个 reducer 应用到相应的 state 属性。现在您正在使用 导出您的减速器export default,它被转换为类似module.exports.default = yourReducer. 当您导入减速器时,您将获得module.exports,它等于{default: yourReducer}您的预加载状态没有default属性,因此 redux 会抱怨。如果你使用import reducer from './blabla'你得到,module.exports.default而不是等于你的减速器。

这里有更多关于 ES6 module系统如何从MDN 工作的信息

从 redux阅读combineReducers文档也可能有所帮助。

要不就:

import yesReducer from './yesReducer';

const store = createStore(combineReducers({
    yesReducer,
    noReducer: (state = {}) => state,
});
import * as reducers from './reducers'

是一种避免核心代码依赖于各种功能实现的好方法。

为了使其工作,您必须指定减速器的名称与您的存储密钥userName相同这可以通过以下方式实现:

在位于 reducers 文件夹中的 index.js 中,执行

export { userNameReducer as userName } from "./UserNameReducer"
export { otherReducer as other } from "./OtherReducer"

另一种方法是直接将导出的减速器重命名为与存储键相同的名称。