You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React.js修改state后组件不重新渲染 购物车点击加号数量不更新问题

问题原因
  • 核心渲染问题:你直接修改了原state数组的引用,未生成新的数组对象。let changeitems = item 是直接将原state数组的内存地址赋值给新变量,修改数组元素属性后调用setItems时,React浅比较发现数组引用没有变化,就会跳过组件重渲染,这就是你修改state后页面不更新的原因。
  • useEffect依赖问题:当前useEffect的依赖数组为空,仅会在组件首次挂载时执行一次,如果父组件传入的items props后续更新,内部的item state不会同步更新。
  • 总价同步问题:修改商品数量后,总价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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 09:18:03