React电商购物车修改单个商品数量时其余商品同步变更问题求助
问题根因
- 核心错误是你在组件全局声明了一个共用的
qty状态,所有购物车商品的数量渲染都绑定了这同一个状态,修改时自然所有商品的数量会同步变化。购物车中每个商品的数量是独立属性,应该存储在对应的商品条目上,不能共用全局状态。 - 状态更新写法错误:
setQty(qty++)使用后置自增,返回的是自增前的原始值,状态更新不会生效,且React状态变更应该使用不可变更新逻辑。 - 删除商品逻辑存在错误:
splice返回的是被删除的元素数组,你直接把返回值存入localStorage,会导致本地存储的购物车数据变为被删除的条目,而非剩余的购物车商品。 - 数量修改后没有同步更新
data状态和localStorage存储的购物车数据,刷新页面后修改会丢失。
修复方案
第一步:调整加购逻辑
在用户点击ADD TO CART存入localStorage时,给每个商品条目默认增加qty: 1的属性,确保每个商品自带独立数量字段。
第二步:修正组件逻辑,替换原有代码
import React from 'react' import { useState, useEffect } from 'react' import '../../src/cart-details.css' import Tooltip from '@material-ui/core/Tooltip'; import Button from '@material-ui/core/Button'; function CartDetails(props) { let {cno}=props; const[data,setData]=useState([]) // 组件挂载时从localStorage读取购物车数据 useEffect(() => { const cart = JSON.parse(localStorage.getItem('cartDetails')) || [] setData(cart) }, []) const incrementQty = (index) =>{ const newData = [...data] newData[index].qty += 1 setData(newData) // 同步更新localStorage localStorage.setItem('cartDetails', JSON.stringify(newData)) } const decrementQty = (index) =>{ const newData = [...data] // 数量最小为1,避免减到负数 if(newData[index].qty > 1) { newData[index].qty -= 1 setData(newData) localStorage.setItem('cartDetails', JSON.stringify(newData)) } } const deleteItem = (index) => { const newData = data.filter((_, i) => i !== index) setData(newData) localStorage.setItem('cartDetails', JSON.stringify(newData)) cno(newData.length) } return ( <> {data.map((item,index)=>( <div className="cart_cont desktop text-dark" key={index}> <div className="innerDiv row m-auto mt-4 d-flex shadow-lg container"> <div className="d-flex justify-content-around align-items-center flex-column col-sm d-flex id"> <label htmlFor="id" className="text-danger fw-bold m-auto">ID</label> <p className="m-auto" id="id">{item.id}</p> </div> <div className="d-flex col-sm thumbnail"> <img src={item.image} className="mt-1 mb-1" alt="image" height="100px" width="80px"/> </div> <div className="d-flex align-items-center flex-column col-sm quantity"> <label htmlFor="title" className="text-danger fw-bold m-auto">Title</label> <p className="m-auto" id="title">{item.title}</p> </div> <div className="d-flex align-items-center col-sm flex-column unitPrice"> <label htmlFor="unitprice" className="text-danger fw-bold m-auto">Unit Price</label> <p className="m-auto unitprice" id="unitprice">Rs. {item.price}</p> </div> <div className="d-flex align-items-center col-sm flex-column unitPrice"> <label htmlFor="unitprice" className="text-danger fw-bold m-auto">Quantity</label> <div className="btns_mob m-auto d-flex flex-row mx-4"> <button className="btn btn-outline-primary mx-1" onClick={()=>decrementQty(index)}>-</button> <button className="btn disabled btn-dark mx-1">{item.qty}</button> <button className="btn btn-outline-primary mx-1" onClick={()=>incrementQty(index)}>+</button> </div> </div> <div className="d-flex align-items-center flex-column col-sm total"> <label htmlFor="total" className="text-danger fw-bold m-auto">Total</label> <p className="m-auto total" id="total">Rs. {item.price * item.qty}</p> </div> <div className="d-flex align-items-center col-sm rmBtn"> <Tooltip title="Delete item"> <i className="far fa-2x m-auto fa-trash-alt" id={index} onClick={(btn)=>{ btn.preventDefault(); deleteItem(index) }}></i></Tooltip> </div> </div> </div> )) } </> ) }
修复说明
- 移除了全局共用的
qty状态,改为读取每个商品条目自带的qty属性渲染数量 - 增减数量时只修改对应下标的商品的
qty值,使用数组展开实现不可变更新,同时同步到localStorage - 重写了删除逻辑,使用filter过滤掉要删除的条目,避免操作原数组和存储错误的返回值
- 自动计算每个商品的小计金额填充到总金额字段
内容的提问来源于stack exchange,提问作者Keerthan Achar
相关产品推荐
相关产品推荐

