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

React实现点击添加按钮仅向购物车发送数组中单个商品

React购物车单商品添加问题修复

问题根因

你当前代码提交全量商品的问题来自两个核心错误,附带一个会导致逻辑失效的语法问题:

  • 渲染商品列表时,添加按钮的点击事件没有传入当前遍历到的单个商品对象,事件回调拿不到目标商品
  • handleClick回调逻辑错误,直接将state中全量商品数组打包提交,没有针对当前点击商品做处理
  • 类代码中componentDidMount方法后多写了一个多余的};,提前闭合了组件类,导致后续的handleClick方法实际定义在类外部,根本无法读取组件实例的state

修复步骤

  1. 修改按钮点击事件绑定,渲染时把当前循环的商品对象传入回调
    把原来的按钮代码:
    <button
      id="btn"
      className="btn btn-primary"
      onClick={this.handleClick}
    >
      Dodaj
    </button>
    
    改成传入当前商品的写法:
    <button
      className="btn btn-primary"
      onClick={() => this.handleClick(prod)}
    >
      Dodaj
    </button>
    
    注:多个按钮复用相同id="btn"不符合HTML规范,直接删除即可
  2. 修复handleClick方法逻辑,仅提交当前选中的单个商品,同时补全JSON请求头(否则json-server无法正确解析请求体写入react-db.json),删除多余的类闭合符号,修复后核心代码如下:
    import React, { Component } from "react";
    import Product from "./Product.jsx";
    import { Kosarica } from "./kosarica.jsx";
    // 已引入的axios可以直接替换手写fetch,简化请求代码
    
    export default class Cart extends Component {
      constructor(props) {
        super(props);
        this.state = {
          products: [],
          cart: [] // 本地维护购物车数据,独立页面可通过全局状态/路由参数读取
        };
      }
    
      componentDidMount = async () => {
        const response = await fetch("http://localhost:5000/products", {
          method: "GET"
        });
        const prods = await response.json();
        this.setState({ products: prods });
      };
    
      // 加购逻辑
      handleClick = async (product) => {
        // 仅提交当前点击的单个商品,补充请求头
        const res = await fetch("http://localhost:5000/cart", {
          method: "POST",
          mode: "cors",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            ...product,
            quantity: 1 // 加购默认数量设为1,和已有的增减逻辑匹配
          })
        });
        const addedItem = await res.json();
        // 同步更新本地购物车state,不用每次操作都重新拉取接口
        this.setState(prev => ({
          cart: [...prev.cart, addedItem]
        }))
        console.log("商品已加入购物车", addedItem);
      };
    
      // 已实现的增减、删除逻辑保持原样即可
      handleIncrement = () => {}
      handleDecrement = () => {}
      handleDelete = () => {}
    
      render() {
        return (
          <div>
            <div className="row">
              {this.state.products.map(prod => {
                return (
                  <Product
                    key={prod.id}
                    product={prod}
                    onIncrement={this.handleIncrement}
                    onDecrement={this.handleDecrement}
                    onDelete={this.handleDelete}
                  >
                    <button
                      className="btn btn-primary"
                      onClick={() => this.handleClick(prod)}
                    >
                      Dodaj
                    </button>
                  </Product>
                );
              })}
            </div>
          </div>
        );
      }
    };
    

更简便的实现方案

如果不需要跨设备、跨浏览器持久化购物车数据,完全不需要每次加购都调用接口存到react-db.json:

  • 可以直接在应用顶层组件维护购物车state,搭配React Context做全局状态下发,所有页面都能直接读取/修改购物车数据
  • 需要刷新页面保留数据的话,加一行逻辑把购物车state同步到localStorage即可,初始化时从本地存储读数据,比调接口响应快很多,实现成本更低
  • 已经引入的axios可以替换手写的fetch,不用手动配置JSON解析、公共请求头,代码会更简洁

内容的提问来源于stack exchange,提问作者Bruno Stojaković

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:51:24