React实现点击添加按钮仅向购物车发送数组中单个商品
React购物车单商品添加问题修复
问题根因
你当前代码提交全量商品的问题来自两个核心错误,附带一个会导致逻辑失效的语法问题:
- 渲染商品列表时,添加按钮的点击事件没有传入当前遍历到的单个商品对象,事件回调拿不到目标商品
handleClick回调逻辑错误,直接将state中全量商品数组打包提交,没有针对当前点击商品做处理- 类代码中
componentDidMount方法后多写了一个多余的};,提前闭合了组件类,导致后续的handleClick方法实际定义在类外部,根本无法读取组件实例的state
修复步骤
- 修改按钮点击事件绑定,渲染时把当前循环的商品对象传入回调
把原来的按钮代码:
改成传入当前商品的写法:<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规范,直接删除即可 - 修复
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ć
相关产品推荐
相关产品推荐

