React中动态添加的多组输入框如何实现独立更新?
问题描述
我有一个React表单,初始包含若干默认的姓名(name)和地址(address)值。当用户点击Add按钮时,会新增一组可输入姓名和地址的输入框,输入内容将存储在additionConfigs状态中。
当前实现中,使用config.id来更新新增的姓名和地址,但存在问题:若用户为同一基础项添加多组输入框,修改其中一组时,同id的其他组也会同步更新。请问如何实现各组输入框的独立更新?是否需要为每组输入框添加唯一标识?
现有代码
import "./styles.css"; import { useState, useEffect } from "react"; export default function App() { const [value, setValue] = useState([]); const [additionConfigs, setAdditionConfigs] = useState([]); useEffect(() => { setTimeout(() => { setValue([ { id: 1, baseName: "XXX", config: { name: "Kenny", address: "New york" } }, { id: 2, baseName: "YYY", config: { name: "Ben", address: "Boston" } }, { id: 3, baseName: "ZZZ", config: { name: "Mary", address: "Los Angeles" } } ]); }, 1000); }, []); const onAddBaseConfig = (item) => { setAdditionConfigs((preValue) => [ ...preValue, { id: item.id, config: { name: "", address: "" } } ]); }; console.log(additionConfigs); const onChangeName = (e, id) => { setAdditionConfigs((preValue) => { const newValue = preValue.map((v) => { if (v.id === id) { return { ...v, config: { ...v.config, name: e.target.value } }; } return v; }); return newValue; }); }; const onChangeAddress = (e, id) => { setAdditionConfigs((preValue) => { const newValue = preValue.map((v) => { if (v.id === id) { return { ...v, config: { ...v.config, address: e.target.value } }; } return v; }); return newValue; }); }; return ( <> {value.length > 0 && value.map((v, index) => ( <div className="item" key={index}> <div className="item"> {v.config.name} {v.config.address} {additionConfigs.length > 0 && additionConfigs .filter((config) => config.id === v.id) .map((config) => ( <div> <label>name</label> <input value={config.config.name} onChange={(e) => onChangeName(e, config.id)} /> <label>address</label> <input value={config.config.address} onChange={(e) => onChangeAddress(e, config.id)} /> </div> ))} </div> <button onClick={() => onAddBaseConfig(v)}>Add</button> </div> ))} </> ); }
解决方案
问题根源在于你用基础项的id作为新增输入框的唯一标识,当同一基础项添加多组输入框时,它们的id完全相同,导致修改时所有同id的输入框都会被更新。必须给每组新增的输入框添加独立的唯一标识,才能实现单独更新。
具体修改步骤:
- 新增输入框时,给每个条目生成唯一标识(可以用时间戳+随机数的组合,生产环境建议用成熟的uuid库)
- 更新输入框内容时,用这个唯一标识来定位要修改的条目,而不是基础项的
id
修改后的代码示例:
import "./styles.css"; import { useState, useEffect } from "react"; // 生成简单的唯一id,生产环境推荐使用uuid库 const generateUniqueId = () => { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; }; export default function App() { const [value, setValue] = useState([]); const [additionConfigs, setAdditionConfigs] = useState([]); useEffect(() => { setTimeout(() => { setValue([ { id: 1, baseName: "XXX", config: { name: "Kenny", address: "New york" } }, { id: 2, baseName: "YYY", config: { name: "Ben", address: "Boston" } }, { id: 3, baseName: "ZZZ", config: { name: "Mary", address: "Los Angeles" } } ]); }, 1000); }, []); const onAddBaseConfig = (item) => { setAdditionConfigs((preValue) => [ ...preValue, { // 新增唯一标识,确保每组输入框独立 uniqueId: generateUniqueId(), // 保留基础项id用于关联对应基础条目 baseId: item.id, config: { name: "", address: "" } } ]); }; const onChangeName = (e, uniqueId) => { setAdditionConfigs((preValue) => preValue.map((v) => v.uniqueId === uniqueId ? { ...v, config: { ...v.config, name: e.target.value } } : v ) ); }; const onChangeAddress = (e, uniqueId) => { setAdditionConfigs((preValue) => preValue.map((v) => v.uniqueId === uniqueId ? { ...v, config: { ...v.config, address: e.target.value } } : v ) ); }; return ( <> {value.length > 0 && value.map((v) => ( <div className="item" key={v.id}> <div className="item"> {v.config.name} {v.config.address} {additionConfigs .filter((config) => config.baseId === v.id) .map((config) => ( <div key={config.uniqueId}> <label>name</label> <input value={config.config.name} onChange={(e) => onChangeName(e, config.uniqueId)} /> <label>address</label> <input value={config.config.address} onChange={(e) => onChangeAddress(e, config.uniqueId)} /> </div> ))} </div> <button onClick={() => onAddBaseConfig(v)}>Add</button> </div> ))} </> ); }
关键改动说明:
- 新增
generateUniqueId函数生成唯一标识,确保每组输入框拥有独立身份 - 修改
additionConfigs结构:用baseId关联对应基础项,用uniqueId作为自身唯一标识 - 更新输入框的修改逻辑,通过
uniqueId精准定位要修改的条目 - 渲染新增输入框时,用
uniqueId作为React列表项的key,符合React的性能优化要求
这样修改后,同一基础项的多组输入框就能独立更新,不会再出现同步修改的问题。
内容的提问来源于stack exchange,提问作者K Pisco
相关产品推荐
相关产品推荐

