React:如何在setState中更新对象数组单个元素并修复输入同步问题
问题修复方案
问题根源
- 输入框同步显示:所有输入框共用同一个
addTagValue状态,导致输入时所有框内容完全一致。 - 添加目标错误:
handleClick中硬编码只修改索引为0的对象,无论点击哪个按钮,新元素只会被加到第一个对象的synonyms列表里。
修复后的代码
import React, { useState } from "react"; export default function App() { const initialSynonyms = [ { id: 1, keyword: "Caffeine", synonyms: ["Coffee", "Espresso"] }, { id: 2, keyword: "Drowsiness", synonyms: ["Sleeping", "Fatigue"] }, { id: 3, keyword: "Drowsiness", synonyms: [""] } ]; const [mysynonyms, setSynonyms] = useState(() => initialSynonyms); // 用对象存储每个词条对应的输入值,以词条id作为键 const [addTagValues, setAddTagValues] = useState(() => initialSynonyms.reduce((acc, item) => { acc[item.id] = ""; return acc; }, {}) ); // 接收词条id,更新对应输入框的内容 const handleChange = (id, e) => { setAddTagValues(prev => ({ ...prev, [id]: e.target.value })); }; // 接收词条id,找到对应词条并添加新同义词 const handleClick = (id) => { setSynonyms(prevValue => prevValue.map(item => { if (item.id === id) { return { ...item, synonyms: [...item.synonyms, addTagValues[id]] }; } return item; }) ); // 清空当前词条对应的输入框 setAddTagValues(prev => ({ ...prev, [id]: "" })); }; return ( <div className="App"> {mysynonyms.map((item) => { return ( // 添加唯一key,避免React列表渲染警告 <div key={item.id}> <p>{item.keyword}</p> {item.synonyms.map((synonym, idx) => ( <span key={idx} style={{ border: "1px solid red", padding: "1px 1px 5px 7px", marginRight: "4px" }} > {synonym} x </span> ))} <div style={{ marginTop: "8px", marginBottom: "16px" }}> <input value={addTagValues[item.id]} className="form-control bg-color2 text-color7 border-end-0 fs-14 fw-bold" type="text" onChange={(e) => handleChange(item.id, e)} /> <button onClick={() => handleClick(item.id)} style={{ marginTop: "4px" }}>add tag</button> </div> </div> ); })} </div> ); }
关键修改点
- 拆分输入状态:将单个
addTagValue改为对象addTagValues,每个词条的id对应独立的输入值,彻底解决输入框同步问题。 - 事件传参明确目标:
handleChange和handleClick都接收词条id,精准定位要操作的词条,避免添加错误。 - 正确更新对象结构:修改同义词列表时,展开原词条对象,避免原代码中出现的对象嵌套错误。
- 添加唯一key:按照React规范给列表元素添加
key,避免渲染异常和控制台警告。
内容的提问来源于stack exchange,提问作者Harshan
相关产品推荐
相关产品推荐

