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

React中购物车商品数量统计与显示的最优实现方案

购物车商品数量统计的最优实现方案

问题描述

我做了一个展示购物车商品的列表视图,每个商品配了增减按钮调整数量。现在的逻辑是通过在数组里添加/删除商品对象来实现增减,但没法显示具体数量。我考虑过两种方案:用useEffect监听商品列表变化统计重复项,或者用useState存商品ID和对应数量的映射。想请教统计单个商品数量的最优方法,以下是我的组件代码:

import React from 'react';
import { Table } from 'react-bootstrap';
import { useFieldArray } from 'react-hook-form';

export const ListArticle = ({ watch, control }) => {
  const list = watch('Articles');

  //listWithoutDuplicates is because i just want to see once my articles even if the quantity is more than 1
  const listWithoutDuplicates = list?.filter(
    (ele, ind) => ind === list?.findIndex((elem) => elem.name === ele.name)
  );

  const { append, remove } = useFieldArray({
    control,
    name: 'Articles',
  });

  const increment = (oneArticle) => {
    append(oneArticle);
  };

  const decrement = (oneArticle) => {
    remove(oneArticle);
  };

   
  return (
    <>
      <Table responsive>
        <thead>
          <tr>
            <th> Name </th>
            <th> Color</th>
            <th> Quantity </th>
          </tr>
        </thead>
        <tbody>
          {listWithoutDuplicates?.map((oneArticle, index) => {
            return (
              <tr key={index}>
                <td>
                  <span>{oneArticle?.name}</span>
                </td>
                <td>
                  <span>{oneArticle?.color}</span>
                </td>
                <td>
                  <button type="button" onClick={() => decrement(oneArticle)}>
                    -
                  </button>
                   <p> HERE MY QUANTITY </p>
                  <button type="button" onClick={() => increment(oneArticle)}>
                    +
                  </button>
          
                </td>   
              </tr>
            );
          })}
        </tbody> 
      </Table>
    </>
  );
};

解决方案

1. 快速统计数量(不修改现有结构)

如果不想改动当前用数组存重复对象的逻辑,可以用reduce高效统计每个商品的数量,比你现在的filter+findIndex性能更好:

// 在组件内添加这段代码,统计每个商品的数量(用name+color做唯一标识,有id的话用id更稳妥)
const articleQuantities = list?.reduce((countMap, item) => {
  const uniqueKey = `${item.name}-${item.color}`;
  countMap[uniqueKey] = (countMap[uniqueKey] || 0) + 1;
  return countMap;
}, {});

然后把渲染数量的地方改成:

<p>{articleQuantities[`${oneArticle.name}-${oneArticle.color}`] || 0}</p>

2. 重构逻辑(推荐方案)

用重复对象存数量的方式太冗余,推荐直接维护「商品标识-数量」的映射,同时和react-hook-form的字段数组同步,逻辑更清晰:

步骤1:新增状态维护数量映射

// 组件内新增状态
const [quantities, setQuantities] = React.useState({});

// 初始化时从现有列表统计数量
React.useEffect(() => {
  const initCounts = list?.reduce((acc, item) => {
    const key = `${item.name}-${item.color}`;
    acc[key] = (acc[key] || 0) + 1;
    return acc;
  }, {});
  setQuantities(initCounts || {});
}, [list]);

步骤2:修改增减按钮逻辑

const increment = (oneArticle) => {
  const key = `${oneArticle.name}-${oneArticle.color}`;
  // 更新数量映射
  setQuantities(prev => ({
    ...prev,
    [key]: (prev[key] || 0) + 1
  }));
  // 同步到react-hook-form的数组
  append(oneArticle);
};

const decrement = (oneArticle) => {
  const key = `${oneArticle.name}-${oneArticle.color}`;
  const currentQty = quantities[key] || 1;

  if (currentQty <= 1) {
    // 数量为1时,删除所有该商品的项
    const targetIndices = list.map((item, idx) => 
      `${item.name}-${item.color}` === key ? idx : null
    ).filter(idx => idx !== null);
    targetIndices.forEach(idx => remove(idx));
    // 从映射中删除该商品
    setQuantities(prev => {
      const newMap = {...prev};
      delete newMap[key];
      return newMap;
    });
  } else {
    // 数量大于1时,删除最后一个该商品的项
    const lastTargetIndex = list.lastIndexOf(item => `${item.name}-${item.color}` === key);
    if (lastTargetIndex !== -1) remove(lastTargetIndex);
    // 更新数量映射
    setQuantities(prev => ({
      ...prev,
      [key]: prev[key] - 1
    }));
  }
};

步骤3:渲染数量

<p>{quantities[`${oneArticle.name}-${oneArticle.color}`] || 0}</p>

3. 额外优化建议

如果你的商品数据里有唯一id字段,把上面的uniqueKey换成item.id,能避免同名同色但实际是不同商品的统计错误。


内容的提问来源于stack exchange,提问作者Elodie Muller

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:21:11