如何在Input的onChange事件中单独修改数组项并实现值求和
问题描述
我有如下对象列表:
[ {id: 182, symbol: 'ETHUSDT', recommended_to_buy_qty: '42.83213', current_qty_in_portfolio: '8.06928'}, {id: 183, symbol: 'XRPUSDT', recommended_to_buy_qty: '83.47332', current_qty_in_portfolio: '8.79834'}, {id: 184, symbol: 'ADAUSDT', recommended_to_buy_qty: '50.72704', current_qty_in_portfolio: '3.79095'} ]
需求是在Input的onChange事件中对数组中每个项的数值进行计算(比如输入值与现有持仓量求和),每次输入变化时重新计算对应项的总和。但目前用单个inputValue状态绑定所有输入控件,导致所有输入值同步变化,想实现每次onChange仅修改数组中的单个项。
当前代码:
const [inputValue, setInputValue] = useState(0) function handleChange(e) { e.preventDefault(); setInputValue(e.target.value); }
输入控件:
<Form.Control onChange={handleChange} value={inputValue} />
解决方案
1. 将整个持仓数组设为状态
把单个inputValue替换为包含所有持仓项的数组状态,给每个项新增inputQty字段存储对应输入框的值:
const [portfolioItems, setPortfolioItems] = useState([ {id: 182, symbol: 'ETHUSDT', recommended_to_buy_qty: '42.83213', current_qty_in_portfolio: '8.06928', inputQty: 0}, {id: 183, symbol: 'XRPUSDT', recommended_to_buy_qty: '83.47332', current_qty_in_portfolio: '8.79834', inputQty: 0}, {id: 184, symbol: 'ADAUSDT', recommended_to_buy_qty: '50.72704', current_qty_in_portfolio: '3.79095', inputQty: 0} ]);
2. 修改事件处理函数,绑定项的唯一标识
让handleChange接收当前项的id,精准定位要更新的项:
function handleChange(id, e) { const newValue = e.target.value; // 遍历数组,只更新对应id的项 setPortfolioItems(prevItems => prevItems.map(item => item.id === id ? {...item, inputQty: Number(newValue)} : item ) ); }
3. 映射生成独立的输入控件
遍历数组生成输入控件,每个控件绑定对应项的id和inputQty值,同时展示计算后的总和:
{portfolioItems.map(item => ( <div key={item.id}> <span>{item.symbol}</span> <Form.Control onChange={(e) => handleChange(item.id, e)} value={item.inputQty} type="number" /> {/* 显示当前项的输入值+持仓量总和 */} <p>当前总和:{(Number(item.inputQty) + Number(item.current_qty_in_portfolio)).toFixed(5)}</p> </div> ))}
4. 计算全局总和(可选)
如果需要统计所有项的总和,用useMemo缓存计算结果,避免重复渲染:
import { useMemo } from 'react'; const totalSum = useMemo(() => { return portfolioItems.reduce((sum, item) => { return sum + Number(item.inputQty) + Number(item.current_qty_in_portfolio); }, 0).toFixed(5); }, [portfolioItems]); // 渲染全局总和 <div>全局总持仓:{totalSum}</div>
关键说明
- 不要用单个状态管理多个输入控件,让每个输入对应数组中单个项的字段,确保输入变化只影响对应项。
- 更新数组状态时,返回新的对象(用扩展运算符
...),保证React能检测到状态变化并重新渲染。 - 数值计算前要把字符串转为数字(
Number()),避免字符串拼接导致错误结果。
内容的提问来源于stack exchange,提问作者KomarCorporation
相关产品推荐
相关产品推荐

