如何通过字符串路径修改React useState深层嵌套对象的状态值
解决方案
核心问题说明
你原来的实现是直接把完整路径字符串当做顶层属性赋值,所以会在payload根目录新增属性,并没有解析路径修改深层嵌套值。同时存在一个隐藏问题:HTMLInputElement的e.target.value永远是字符串类型,你原来对值类型的判断逻辑永远不会触发数值分支。
实现代码
第一步:修改handleChange函数,新增路径解析与深层更新逻辑
const handleChange = (path: string) => (e: React.ChangeEvent<HTMLInputElement>) => { // 将点分隔的路径拆分为层级数组 const keys = path.split('.'); // 根据字段类型转换输入值,这里可以根据业务规则调整判断逻辑 const targetValue = e.target.value; const value = keys.at(-1) === 'initialDownloadLength' ? Number(targetValue) : targetValue; // immutable方式更新嵌套对象,避免直接修改原state setPayload(prev => { const newPayload = {...prev}; let currentLevel = newPayload; // 逐层遍历路径,生成每一层的新对象引用 for (let i = 0; i < keys.length - 1; i++) { currentLevel[keys[i]] = {...currentLevel[keys[i]]}; currentLevel = currentLevel[keys[i]]; } // 给最内层目标属性赋值 currentLevel[keys.at(-1)] = value; return newPayload; }); };
如果你的嵌套对象层级很深、字段类型复杂,可以用
structuredClone直接深拷贝原state,简化层级拷贝逻辑:setPayload(prev => { const newPayload = structuredClone(prev); let currentLevel = newPayload; for (let i = 0; i < keys.length - 1; i++) { currentLevel = currentLevel[keys[i]]; } currentLevel[keys.at(-1)] = value; return newPayload; })
第二步:调用方式保持一致
直接传入完整的点分隔路径即可正常更新深层属性:
<input type="number" value={payload.downloadConfiguration.product.initialDownloadLength} onChange={handleChange("downloadConfiguration.product.initialDownloadLength")} />
扩展适配
如果需要全局适配数值类型字段,不用硬编码判断属性名,可以给input添加自定义属性标识类型:
<input type="number" data-value-type="number" value={payload.downloadConfiguration.product.initialDownloadLength} onChange={handleChange("downloadConfiguration.product.initialDownloadLength")} />
然后在handleChange中读取自定义属性做类型转换即可:
const value = e.target.dataset.valueType === 'number' ? Number(targetValue) : targetValue;
内容的提问来源于stack exchange,提问作者mdbej
相关产品推荐
相关产品推荐

