React中加入购物车触发无限循环的修复及商品传值方法
问题原因
- 核心触发点是JSX事件绑定语法错误:你写的
<button onClick=()=>handlecart(product)>漏了包裹回调的大括号,不符合JSX语法规则,会导致回调在组件渲染阶段被直接执行,而不是点击时才触发。渲染阶段执行setCount、setItem会触发组件重渲染,重渲染又再次执行回调触发状态更新,直接形成「渲染→更新状态→重渲染」的无限循环,表现就是购物车数量无故持续上涨。 - 状态设计不合理:你单独拆分了
count和item两个状态存购物车数据,既不支持多商品加入购物车的场景,setCount(count+1)的写法还存在闭包陷阱,连续触发更新时会拿到旧的count值,导致计数错误。 - 如果你把商品对象直接作为props传给子组件时,父组件每次渲染都会在map里生成新的箭头函数引用,也会导致子组件不必要的重渲染,放大循环问题。
正确实现方式
- 重构购物车状态,直接用数组存储所有选中的商品,不需要单独维护count状态,购物车总数量可以通过数组计算得到。
- 修正onClick语法,用大括号包裹事件回调,确保回调只在点击时触发。
- 状态更新使用函数式写法,规避闭包导致的旧值问题,同时可以直接实现「重复加购商品自动累加数量」的逻辑。
完整修正后的核心代码:
// 定义购物车状态,初始为空数组 const [cartItems, setCartItems] = useState([]) // 加入购物车逻辑 const handleCart = (product) => { setCartItems(prevCart => { // 判断当前商品是否已经在购物车中 const isExist = prevCart.some(item => item._id === product._id) if (isExist) { // 已存在则对应商品数量+1 return prevCart.map(item => item._id === product._id ? {...item, count: (item.count || 1) + 1} : item ) } // 不存在则新增商品到数组,默认购买数量为1 return [...prevCart, {...product, count: 1}] }) } // 列表渲染部分,只需要修正onClick的语法 {localitem.map((product) => ( <div key={product._id} className="group relative"> <div> <img src={product.image} alt={"image"} className="w-full h-full object-center object-cover lg:w-full lg:h-full" /> </div> <div className="mt-4 flex justify-between"> <div> <h3 className="text-sm text-gray-700 font-semibold"> {product.name} </h3> <h4 className="text-base font-medium text-gray-900"> Price<p className="inline-block line-through">{product.price}</p> ${product.price} </h4> </div> <div className="px-3"> <button>buy</button> {/* 这里给回调加上大括号包裹 */} <button onClick={() => handleCart(product)}>cart</button> </div> </div> </div> ))}
后续需要传递数据到订单页面时,直接传
cartItems数组即可,购物车总商品数可以通过cartItems.reduce((sum, item) => sum + item.count, 0)计算,不会出现计数异常问题。
内容的提问来源于stack exchange,提问作者Dexter
相关产品推荐
相关产品推荐

