简体   繁体   English

Redux preloadedState 导致默认减速器状态的覆盖(以及随后的未定义错误)?

[英]Redux preloadedState causing override (and subsequent undefined error) of default reducer state?

I currently am creating a website with react-redux and was getting an error with a typo in the preloadedState variable within createStore.我目前正在使用 react-redux 创建一个网站,并且在 createStore 中的 preloadedState 变量中出现拼写错误。 My relevant store code is as follows (Note the cartitems spelling in initialState instead of cartItems ):我的相关商店代码如下(注意在initialStatecartitems拼写而不是cartItems ):

const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
})

const cartItemsFromStorage = localStorage.getItem('cartItems') ? 
    JSON.parse(localStorage.getItem('cartItems')) : []

//BELOW GETS PASSED INTO createStore
const initialState = {
    cart: {cartitems: cartItemsFromStorage}
}

Within my cartReducer the code being affected is as follows:在我的cartReducer中,受影响的代码如下:

export const cartReducer = (state = {cartItems: []}, action) => {
switch(action.type){
    case CART_ADD_ITEM:
        const item = action.payload
        const existItem = state.cartItems.find(x => x.product === item.product)
        ***other code below...***
    default:
        return state
}

I noticed that this throws an Unhandled Rejection (TypeError): state.cartItems is undefined error on the existItem line.我注意到这会引发Unhandled Rejection (TypeError): state.cartItems is undefined error on the existItem行。 Why does the addition of the preloadedState cause this issue?为什么添加 preloadedState 会导致这个问题? From my understanding the reducer's default state (in this case given by state = {cartItems: []} ) should still be accessible from within the reducer?根据我的理解,reducer 的默认状态(在这种情况下由state = {cartItems: []} )应该仍然可以从 reducer 内部访问? Is this not the case?不是这样吗?

This is by design.这是设计使然。 From the doc Initializing State :从文档初始化状态

Without combineReducers() or similar manual code, preloadedState always wins over state = ... in the reducer because the state passed to the reducer is preloadedState and is not undefined , so the ES6 argument syntax doesn't apply.如果没有combineReducers()或类似的手动代码, preloadedState总是在 reducer 中胜过state = ...因为传递给 reducer 的 state 是preloadedState而不是undefined ,所以 ES6 参数语法不适用。

With combineReducers() the behavior is more nuanced.使用combineReducers()行为更加微妙。 Those reducers whose state is specified in preloadedState will receive that state.状态在preloadedState指定的那些 reducer 将接收该状态。 Other reducers will receive undefined and because of that will fall back to the state = ... default argument they specify.其他减速器将收到undefined ,因此将退回到state = ...默认参数。

For your case, the preloadedState is {cart: { cartitems: cartItemsFromStorage }} , the { cartitems: cartItemsFromStorage } object will be passed in cartReducer as it's default state rather than the ES6 default argument syntax .对于您的情况, preloadedState{cart: { cartitems: cartItemsFromStorage }}{ cartitems: cartItemsFromStorage }对象将在cartReducer作为默认状态而不是 ES6 默认参数语法传递。

That's why your cart state shape is {cartitems: cartItemsFromStorage}这就是为什么您的购物车状态形状是{cartitems: cartItemsFromStorage}

If the preloadedState is undefined , then your cart default state is {cartItems: []} .如果preloadedStateundefined ,那么您的购物车默认状态是{cartItems: []}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM