React中如何更新嵌套对象内同名不同值的输入状态?
如何通过单个onChange精准更新嵌套对象状态
首先要明确你当前状态结构的致命问题:JavaScript对象不允许重复键名,你写的the_data里多个同名的key、nested_key1里重复的value_to_be_changed,都会被最后一个值覆盖,实际运行时状态只会保留最后一个key和每个嵌套对象里最后一个value_to_be_changed。第一步必须修正状态结构,给每个键设置唯一名称,或用数组存储同类型对象:
修正后的合法状态结构示例
const the_data = { key1: { nested_key1: { value1: 1, value2: 1 }, nested_key2: { value1: 1, value2: 50 } }, key2: { valueA: 1, valueB: 80, valueC: 2.0 }, key3: { valueA: 1, valueB: 80, valueC: 2.0 } };
核心解决方案:用name属性携带完整嵌套路径
要精准更新单个字段,需让每个输入框的name属性包含从根到目标字段的完整路径(比如key1.nested_key1.value1),在onChange事件中解析这个路径,逐层进行不可变更新(避免直接修改原状态)。
通用嵌套状态更新实现(React + TypeScript)
// 解析嵌套路径的工具函数 const updateNestedField = <T>(obj: T, path: string, value: any): T => { const keys = path.split('.'); return keys.reduce((acc, key, index) => { // 最后一个键直接赋值 if (index === keys.length - 1) { return { ...acc, [key]: value }; } // 非最后一个键递归创建新对象,保持不可变 return { ...acc, [key]: updateNestedField(acc[key] || {}, keys.slice(index + 1).join('.'), value) }; }, { ...obj } as T); }; // 统一的onChange处理函数 const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; // 按需转换输入值类型(比如转数字) const parsedValue = isNaN(Number(value)) ? value : Number(value); updateData2(prevState => { const newTheData = updateNestedField(prevState.body.the_data, name, parsedValue); return { ...prevState, body: { ...prevState.body, the_data: newTheData } }; }); };
输入框的name属性写法示例
<input type="number" name="key1.nested_key1.value1" value={data.body.the_data.key1.nested_key1.value1} onChange={handleChange} />
你当前代码的问题总结
- 重复键名导致状态结构无效,必须先修正
- 类型定义语法错误:
type T = keyof typeof newVal.body.key.nested_key1.;末尾多了点,且无需在函数内部重复定义类型 - 不可变更新不彻底:仅浅拷贝了外层对象,嵌套对象还是引用类型,直接修改会污染原状态
- 路径硬编码:无法区分不同的
key和嵌套层级,必须通过name属性动态获取路径
内容的提问来源于stack exchange,提问作者Alwaz
相关产品推荐
相关产品推荐

