React渲染中保持初始值恒定,修复购物车价格计算错误
问题分析
你的核心问题是没有保留商品的初始单价,而是直接把price字段当作总价修改,导致增减数量时计算逻辑完全出错。比如:
- 初始状态:unit=1,price=150(此时price是单价)
- 第一次点击+:代码里存在未定义的
unit变量,导致总价没按预期更新为2*150 - 第二次点击+:此时price已经是错误值,基于它计算自然得不到正确的450
另外代码还有几个基础错误:
usestate应为useState(React Hook大小写敏感)- 渲染时
item.IMG、item.product、quantity都是错误的属性名,对应应为item.img、item.name、item.unit addToCart里的console.log(cartItem)拿不到最新状态,因为setState是异步操作
修复方案
1. 调整购物车项结构,固定初始单价
添加商品到购物车时,单独存储初始单价(比如命名为basePrice),后续计算总价始终基于这个固定值,避免修改原单价:
const addToCart = (product) => { // 先检查商品是否已在购物车,避免重复添加 const exists = cartItem.find(item => item.id === product.id); if (exists) { addQuantity(product.id); return; } // 新商品保留初始单价,unit初始为1,总价由初始单价*数量计算 setCartItem(prev => [...prev, {...product, basePrice: product.price}]); };
2. 修正增减数量的计算逻辑
基于basePrice计算总价,不再用错误的当前price反向推导:
const addQuantity = (id) => { setCartItem(prev => prev.map(item => { if (item.id === id) { const newUnit = item.unit + 1; return {...item, unit: newUnit, price: item.basePrice * newUnit}; } return item; })); }; const reduceQuantity = (id) => { setCartItem(prev => prev.map(item => { if (item.id === id && item.unit > 1) { const newUnit = item.unit - 1; return {...item, unit: newUnit, price: item.basePrice * newUnit}; } return item; })); };
如果你不想在state里存储总价,也可以直接在渲染时计算
{item.basePrice * item.unit},这样state只需要保留basePrice和unit,结构更简洁。
3. 修正渲染部分的属性错误
<div> {cartItem.map((item) => { return ( <div key={item.id}> {/* 必须添加key属性,React列表渲染要求 */} <button onClick={() => addQuantity(item.id)}>+</button> <img src={item.img} alt={item.name} /> <h3 className="name">{item.name}</h3> <p className="price">${item.price}</p> <p className="quantity">{item.unit}</p> <button onClick={() => reduceQuantity(item.id)}>-</button> </div> ); })} </div>
完整修正后的核心代码示例
import { useState } from 'react'; const products = [ { id: 1, name: "Oppo", price: 200, unit: 1, img: "oppo.jpg" }, { id: 2, name: "Samsung", price: 250, unit: 1, img: "samsung.jpg" }, { id: 3, name: "Vivo", price: 150, unit: 1, img: "vivo.jpg" }, ]; const Cart = () => { const [cartItem, setCartItem] = useState([]); const addToCart = (product) => { const exists = cartItem.find(item => item.id === product.id); if (exists) { addQuantity(product.id); return; } setCartItem(prev => [...prev, {...product, basePrice: product.price}]); }; const addQuantity = (id) => { setCartItem(prev => prev.map(item => { if (item.id === id) { const newUnit = item.unit + 1; return {...item, unit: newUnit, price: item.basePrice * newUnit}; } return item; })); }; const reduceQuantity = (id) => { setCartItem(prev => prev.map(item => { if (item.id === id && item.unit > 1) { const newUnit = item.unit - 1; return {...item, unit: newUnit, price: item.basePrice * newUnit}; } return item; })); }; return ( <div> {/* 商品展示区 */} <div className="product-list"> {products.map(product => ( <div key={product.id} className="product-item"> <img src={product.img} alt={product.name} /> <h3>{product.name}</h3> <p>${product.price}</p> <button onClick={() => addToCart(product)}>加入购物车</button> </div> ))} </div> {/* 购物车区 */} <div className="cart-container"> {cartItem.map((item) => ( <div key={item.id} className="cart-item"> <button onClick={() => addQuantity(item.id)}>+</button> <img src={item.img} alt={item.name} /> <h3 className="name">{item.name}</h3> <p className="price">${item.price}</p> <p className="quantity">{item.unit}</p> <button onClick={() => reduceQuantity(item.id)}>-</button> </div> ))} </div> </div> ); }; export default Cart;
内容的提问来源于stack exchange,提问作者user25549839
相关产品推荐
相关产品推荐

