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

React Hooks向state新增购物车项报cartList不可迭代TypeError

错误产生原因

报错的核心触发点是cartList的类型和预期不符,具体问题点如下:

  • localStorage读取的兜底值错误:useEffect中写的兜底逻辑是localStorage.getItem("cartList") || "{}",当本地没有存储过cartList时,会拿到字符串"{}",解析后是普通对象{},而非初始state定义的数组。扩展运算符...只能作用于数组、Set这类实现了迭代接口的可迭代对象,普通对象没有迭代器,执行[...cartList, cartItem]时就会抛出cartList is not iterable的错误。
  • 状态更新存在时序问题:React的state更新是异步的,调用setCartItem后不会立刻修改cartItem的值,后续拼接购物车列表时拿到的还是更新前的旧cartItem,会导致添加的商品数据不对。
  • localStorage写入时机错误:同样因为setCartList是异步更新,调用setCartList后立刻读取cartList写入localStorage,拿到的是更新前的旧值,会出现本地存储和页面状态不一致的问题。
  • 重复商品判断逻辑缺失:代码中定义了itemIndex但从未修改其值,永远为-1,会导致重复点击同一商品时重复添加数据。
修复方案

修正后的完整可运行代码如下:

import { useState, useEffect } from "react";
import { Button } from "react-bootstrap";

export default function App() {
  // 初始化时直接从localStorage读取购物车数据,兜底为空数组
  const [cartList, setCartList] = useState(() => {
    const localCart = localStorage.getItem("cartList");
    return localCart ? JSON.parse(localCart) : [];
  });
  // 单个购物车商品为对象类型,初始值设为空对象即可
  const [cartItem, setCartItem] = useState({});

  // 监听cartList变化,自动同步到localStorage,保证数据一致
  useEffect(() => {
    localStorage.setItem("cartList", JSON.stringify(cartList));
  }, [cartList]);

  const handleClick = (e) => {
    e.preventDefault();
    const arr = e.target.id.split("-");
    const selectID = arr[1];
    const newItem = { id: selectID };

    // 补全重复商品判断逻辑
    const itemIndex = cartList.findIndex(item => item.id === selectID);
    if (itemIndex < 0) {
      // 用函数式更新获取最新的cartList值,避免闭包导致的旧值问题
      setCartList(prevList => [...prevList, newItem]);
    }
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Button
        variant="link"
        id="item-12"
        onClick={handleClick}
      >
        item no.12
      </Button>
      <Button
        variant="link"
        id="item-100"
        onClick={handleClick}
      >
        item no.100
      </Button>
      <div>当前购物车内容:{JSON.stringify(cartList)}</div>
    </div>
  );
}

核心修改点:

  • 修正localStorage兜底值为数组类型,保证cartList永远是可迭代的数组,从根源解决类型不匹配的报错;同时把读取本地存储的逻辑放到useState初始化函数中,避免首次渲染和useEffect执行间隙的状态不一致。
  • 移除点击事件中冗余的cartItem状态更新,直接构造新商品对象使用,规避state异步更新拿不到最新值的问题。
  • 新增独立的useEffect监听cartList变化,只要购物车数据更新就自动同步到localStorage,不用在每个修改cartList的位置重复写存储逻辑,保证本地数据和页面状态始终一致。
  • 补全重复商品判断逻辑,通过findIndex检测当前选中商品是否已存在于购物车,避免重复添加。
  • 所有cartList更新操作使用函数式写法,直接从参数中拿到最新的state值,规避闭包陷阱导致的旧值问题。

内容的提问来源于stack exchange,提问作者dapidmini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:06:23