React购物车商品数量增减按钮点击后页面消失问题排查
购物车数量增减按钮点击后页面消失问题修复
问题描述
用Material UI构建表单与表格单元格,编写了一段React购物车代码,该代码可在localhost:3000正常显示内容,但点击数量增减按钮时页面会消失,怀疑是useState函数使用不当。相关代码如下:
原State与处理函数代码
const[products,setProducts]=useState([ { 'cartItems':[ { name: 'Cherry', quantity: 1, image:"https://media.istockphoto.com/photos/cherry-trio-with-stem-and-leaf-picture-id157428769?b=1&k=20&m=157428769&s=170667a&w=0&h=F1PxAjsNGhS0svv0t_kMRYdAE3UGISZD_BY066-SubU=", price:200, }, { name:'Almonds', quantity:1, image:"https://media.istockphoto.com/photos/almonds-picture-id153711056?b=1&k=20&m=153711056&s=170667a&w=0&h=8exR9-QE1WweR4ijYM7XdlELsrKBYLQyi7ILRexnHg4=", price :100 }, { name:'Onions', quantity:1, image:'https://media.istockphoto.com/photos/red-onion-slice-picture-id175448479?b=1&k=20&m=175448479&s=170667a&w=0&h=kcjadYpPSifmgaESFhA7EKVMdLmL-pXPhrwSvJM0o2U=', price : 200 } ], 'totalPrice':500, 'count':3 } ]); const handleDecrement = (prod_name) =>{ setProducts(products => products[0].cartItems.map((product) => prod_name===product.name ? {...product,quantity:product.quantity-(product.quantity > 1 ? 1 :0)}:product ) ); } const handleIncrement = (prod_name) => { setProducts(products => products[0].cartItems.map((product) => prod_name===product.name ? {...product,quantity:product.quantity+1}:product ) ); }
原表格单元格代码
<TableCell align="left" size="small" width={10}> <form> <div class="value-button" id="decrease" onClick={()=>handleDecrement(product.name)} value="Decrease Value"><RemoveIcon/></div> <input type="number" id='number' value={product.quantity} /> <div class="value-button" id="increase" onClick={()=>handleIncrement(product.name)} value="Increase Value"><AddIcon/></div> </form> </TableCell>
问题分析
- State结构被破坏:
setProducts调用直接返回了cartItems数组,原本的products是包含cartItems、totalPrice、count的对象数组,修改后products变成了纯商品项数组,后续渲染时找不到原有结构,导致页面崩溃。 - 表单默认提交:点击按钮时触发了表单的默认提交行为,导致页面刷新。
修复代码
修改后的处理函数
const handleDecrement = (prod_name) => { setProducts(prevProducts => { // 复制原数组中的第一个购物车对象 const updatedCart = {...prevProducts[0]}; // 更新对应商品的数量,确保不小于1 updatedCart.cartItems = updatedCart.cartItems.map(product => prod_name === product.name ? {...product, quantity: Math.max(product.quantity - 1, 1)} : product ); // 重新计算总价和商品总数 updatedCart.totalPrice = updatedCart.cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0); updatedCart.count = updatedCart.cartItems.reduce((total, item) => total + item.quantity, 0); // 返回保持原结构的数组 return [updatedCart]; }); }; const handleIncrement = (prod_name) => { setProducts(prevProducts => { const updatedCart = {...prevProducts[0]}; updatedCart.cartItems = updatedCart.cartItems.map(product => prod_name === product.name ? {...product, quantity: product.quantity + 1} : product ); // 同步更新总价和总数 updatedCart.totalPrice = updatedCart.cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0); updatedCart.count = updatedCart.cartItems.reduce((total, item) => total + item.quantity, 0); return [updatedCart]; }); };
修改后的表格单元格代码(阻止表单提交)
<TableCell align="left" size="small" width={10}> <form onSubmit={(e) => e.preventDefault()}> {/* 阻止表单默认提交行为 */} <div className="value-button" id="decrease" onClick={()=>handleDecrement(product.name)} value="Decrease Value"><RemoveIcon/></div> <input type="number" id='number' value={product.quantity} readOnly /> {/* 设置只读避免手动输入干扰 */} <div className="value-button" id="increase" onClick={()=>handleIncrement(product.name)} value="Increase Value"><AddIcon/></div> </form> </TableCell>
关键说明
- 始终保持
products的原数组结构,只修改内部对象的字段,避免结构突变导致渲染错误。 - 阻止表单默认提交行为,彻底解决页面刷新问题。
- 同步更新
totalPrice和count,保证购物车数据一致性。 - 给数量输入框添加
readOnly,避免用户手动修改数量引发的额外逻辑问题。
内容的提问来源于stack exchange,提问作者Nancy Tindwani
相关产品推荐
相关产品推荐

