You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React新手技术求助:添加商品至购物车后无法在购物车页面显示,报错state.cartItems is not iterable

Hey there! Let's fix that state.cartItems is not iterable error and get your shopping cart working as expected. The core issue lies in how you're updating the state in your cartReducer—you're accidentally mangling the state structure when returning new state objects.

1. Fix the Reducer State Updates

Right now, in every case of your reducer, you're spreading state.cartItems (an array) instead of state (the object that contains cartItems). This breaks your state structure: instead of keeping cartItems as an array, you're turning your root state into a copy of the cart items array, which means subsequent attempts to iterate over cartItems fail because it no longer exists as an array property.

Here's the corrected reducer code:

const initialState = {
  cartItems: localStorage.getItem('cartItems') 
    ? JSON.parse(localStorage.getItem('cartItems')) 
    : []
}

export const cartReducer = (
  state = initialState,
  action
) => {
  switch (action.type) {
    case CART_ADD_ITEM:
      const item = action.payload
      const existItem = state.cartItems.find((x) => x.product === item.product)
      
      let updatedCartItems
      if (existItem) {
        updatedCartItems = state.cartItems.map((x) =>
          x.product === existItem.product ? item : x
        )
      } else {
        updatedCartItems = [...state.cartItems, item]
      }

      // Sync with localStorage to persist cart across page refreshes
      localStorage.setItem('cartItems', JSON.stringify(updatedCartItems))
      return { ...state, cartItems: updatedCartItems }

    case CART_REMOVE_ITEM:
      const filteredCartItems = state.cartItems.filter((x) => x.product !== action.payload)
      localStorage.setItem('cartItems', JSON.stringify(filteredCartItems))
      return { ...state, cartItems: filteredCartItems }

    default:
      return state
  }
}

Key changes here:

  • We start with an initialState that loads cart items from localStorage (so cart persists after page reloads)
  • We always spread the original state object (...state) to preserve any other state properties, then update only the cartItems property
  • We sync the updated cart items to localStorage directly in the reducer, ensuring the stored data is always in sync with Redux state

Since we've guaranteed cartItems will always be an array (thanks to the initial state), you can remove the optional chaining (?.) in your CartScreen component for cleaner code:

// Replace cartItems?.length with cartItems.length
{cartItems.length === 0 ? (
  <Message>
    Your cart is empty <Link to='/'>Go Back</Link>
  </Message>
) : (
  <ListGroup variant='flush'>
    {cartItems.map((item) => (
      // ... rest of the list item code
    ))}
  </ListGroup>
)}

// And in the subtotal section:
<h2>
  Subtotal ({cartItems.reduce((acc, item) => acc + item.qty, 0)}) items
</h2>
Rs. {cartItems.reduce((acc, item) => acc + item.qty * item.price, 0).toFixed(2)}

3. Fix Action Sync with LocalStorage

In your original cart action, you were trying to save to localStorage immediately after dispatching, but Redux state updates are asynchronous. By moving the localStorage sync into the reducer, we avoid this race condition entirely—now every state change to cartItems automatically updates localStorage.

After making these changes, your cart should:

  • Display items correctly when added
  • No longer throw the "not iterable" error
  • Calculate subtotal quantity and price properly
  • Persist cart items across page refreshes

内容的提问来源于stack exchange,提问作者melee-master

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 21:07:40