React.js修改state后组件不重新渲染 购物车点击加号数量不更新问题
问题原因
- 核心渲染问题:你直接修改了原state数组的引用,未生成新的数组对象。
let changeitems = item是直接将原state数组的内存地址赋值给新变量,修改数组元素属性后调用setItems时,React浅比较发现数组引用没有变化,就会跳过组件重渲染,这就是你修改state后页面不更新的原因。 - useEffect依赖问题:当前useEffect的依赖数组为空,仅会在组件首次挂载时执行一次,如果父组件传入的
itemsprops后续更新,内部的itemstate不会同步更新。 - 总价同步问题:修改商品数量后,总价
total没有同步重新计算。
修复方案
1. 核心逻辑修改要点
- 修改数组/对象state时,始终生成新的引用,避免直接修改原state
- 补充useEffect依赖,抽离总价计算逻辑复用
- 给数量减少操作增加下限判断,避免出现负数数量
2. 修改后完整代码
import { Fragment, useState, useEffect } from "react"; const Cartitemscreater = ({ items ,cartUpdater}) => { const [total, setTotal] = useState(0); const [item, setItems] = useState([]); const [available,setAvailable] = useState(true) // 抽离总价计算逻辑复用 const calcTotal = (list) => { let totalPr = 0; for (let index = 0; index < list.length; index++) { let price = parseInt(list[index].productprice); totalPr += price * list[index].qty; } setTotal(totalPr); } useEffect(() => { setItems(items); calcTotal(items); setAvailable(items.length > 0); // 补充依赖items,props变化时同步更新内部state }, [items]); const handlePlus = (number, index) => { const Nnumber = number + 1; // 生成新数组,替换原引用 const changeItems = [...item]; // 生成新的商品对象,避免深层修改原state changeItems[index] = {...changeItems[index], qty: Nnumber}; setItems(changeItems); localStorage.setItem("items", JSON.stringify(changeItems)); // 更新总价 calcTotal(changeItems); }; const handleMinus = (number, index) => { // 数量下限为1,避免出现负数 if(number <= 1) return; const Nnumber = number - 1; const changeItems = [...item]; changeItems[index] = {...changeItems[index], qty: Nnumber}; setItems(changeItems); localStorage.setItem("items", JSON.stringify(changeItems)); calcTotal(changeItems); }; const handleDelete = (_id,index)=>{ const deleteState = item.filter(i => i._id !== _id); setItems(deleteState); cartUpdater(deleteState.length); if(deleteState.length===0){ setAvailable(false) localStorage.removeItem("items") return; } localStorage.setItem("items",JSON.stringify(deleteState)) calcTotal(deleteState); } return ( <Fragment> { available ?<div className="container my-5"> <div className="table-responsive-xl"> <table class="table mt-5 "> <thead> <tr> <th scope="col">Product image</th> <th scope="col">Product title</th> <th scope="col">Product price</th> <th scope="col">Product quantity </th> </tr> </thead> { item.map((eachItem, index) => { return ( <tbody key={eachItem._id} className="shadow"> <tr> <td> <img src={`/products/${eachItem._id}/${eachItem.prImage}`} className="img-fluid imgs " alt="somethings" style={{ width: "130px", height: "80px", objectFit:"cover" }} /> <p><small className="text-muted">{eachItem.productdescription}</small></p> <span onClick={()=>{ handleDelete(eachItem._id,index) }}><i class="bi bi-trash fs-4 text-danger"></i></span> </td> <td>{eachItem.producttitle}</td> <td className="fw-bold">$ {eachItem.productprice}</td> <td> <span onClick={(e) => { handleMinus(eachItem.qty, index); }} > {" "} <i className="bi bi-dash-circle-fill text-danger"></i> </span> <span className="mx-2"> {eachItem.qty}</span> <span onClick={(e) => { handlePlus(eachItem.qty, index); }} > <i className="bi bi-plus-circle-fill text-success"></i>{" "} </span> </td> </tr> </tbody> ); })} </table> </div> </div>: <p className="mt-lg-5 fw-bold text-danger fs-4"> {"Cart is empty "}<i class="bi bi-cart-fill"></i> </p> } </Fragment> ); }; export default Cartitemscreater;
内容的提问来源于stack exchange,提问作者node Dev
相关产品推荐
相关产品推荐

