React中如何让映射数组内的输入框值独立修改
解决React商品数量输入框同步变化的问题
你遇到的问题根源是所有商品项共享了同一个amount状态变量,所以修改任意一个输入框都会让所有输入框同步更新。要实现独立控制每个商品的数量,需要用对象类型的状态,以商品ID为键来存储对应商品的数量。
下面是修改后的完整代码,关键改动已标注:
import React, { useState } from "react"; import "./produce.css"; import produce from "../produce.json"; import { MdArrowDropUp, MdArrowDropDown } from "react-icons/md"; const Produce = () => { // 1. 将单个状态改为对象,以商品id为键存储数量,初始值为空(或提前初始化所有商品为0) const [amounts, setAmounts] = useState({}); // 2. 修改增减函数,接收商品id,只更新对应商品的数量 const handleIncrease = (id) => { setAmounts(prev => { const currentAmount = prev[id] || 0; return { ...prev, [id]: currentAmount < 20 ? currentAmount + 1 : 20 }; }); }; const handleDecrease = (id) => { setAmounts(prev => { const currentAmount = prev[id] || 0; return { ...prev, [id]: currentAmount > 0 ? currentAmount - 1 : 0 }; }); }; // 3. 修改输入框change事件,针对当前商品id更新数量,同时做边界和类型处理 const handleChange = (e, id) => { let value = Number(e.target.value); // 确保输入是有效数字,且在0-20范围内 if (isNaN(value)) value = 0; if (value < 0) value = 0; if (value > 20) value = 20; setAmounts(prev => ({ ...prev, [id]: value })); }; return ( <div className="produce"> {produce.map((item) => { // 4. 每个输入框绑定对应商品id的数量,默认值为0 const itemAmount = amounts[item.id] || 0; return ( <div className="produce_item" key={item.id}> <img className="item_img" src={item.img} /> <div className="produce_explain"> <div className="produce_explain1"> <h3>{item.name}</h3> {item.iconOrganic && <img src={item.iconOrganic} />} </div> <div className="produce_explain2"> {item.organic === "organic" && <h5>{item.organic}</h5>} <div className="produce_weight"> <h6>approx.</h6> {item.weight} </div> </div> <div className="produce_price"> <h3>{item.price} $</h3> </div> </div> <div className="produce_buy"> <button className="produce_cart">Add to Cart</button> <div className="produce_number"> {/* 5. 点击按钮时传入当前商品id */} <button className="produce_increase" onClick={() => handleIncrease(item.id)}> <MdArrowDropUp /> </button> <input type="number" {/* 建议改成number类型,限制输入为数字 */} className="produce_count" value={itemAmount} onChange={(e) => handleChange(e, item.id)} min="0" max="20" {/* 加上输入框的边界限制 */} /> <button className="produce_decrease" onClick={() => handleDecrease(item.id)}> <MdArrowDropDown /> </button> </div> </div> </div> ); })} </div> ); }; export default Produce;
关键改动说明:
- 状态结构调整:从单个
amount变量改为amounts对象,每个商品ID对应自己的数量值,实现独立存储。 - 事件函数适配:增减和输入变更函数都接收商品ID作为参数,只更新对应ID的数量,不影响其他商品。
- 输入优化:将输入框类型改为
number,并添加min和max属性,配合代码中的边界检查,确保输入值合法。 - 默认值处理:当商品还没有数量记录时,用
|| 0默认显示0,避免输入框出现空值。
内容的提问来源于stack exchange,提问作者Utku AKTAS
相关产品推荐
相关产品推荐

