ReactJS如何更新数组渲染文本及嵌套子节点的questionsAnswers字段
问题核心原因
你的代码存在3个核心问题导致子节点修改不生效、且无法同步更新:
- 状态更新逻辑仅处理了第一层国家的
questionsAnswers字段,完全没有涉及子节点州的对应数据 - 子节点输入触发回调时,没有传入当前所属子节点的索引,回调无法定位要修改的子节点数据
- 原
setMyData写法错误:myData是数组类型,你用对象展开{...myData}会把数组转成键为索引的对象,导致后续数组方法失效
修复后完整代码
import React, { useState } from 'react'; const data = [ { name: "USA", questionsAnswers: [ { id: 1, name: "Validated" }, { id: 2, name: "Non Validate" }, { id: 3, name: "None" } ], children: [ { name: "ALABAMA", questionsAnswers: [ { id: 1, name: "Validated" }, { id: 2, name: "Non Validate" }, { id: 3, name: "None" } ], }, { name: "FLORIDA", questionsAnswers: [ { id: 1, name: "Validated" }, { id: 2, name: "Non Validate" }, { id: 3, name: "None" } ], } ] } ]; const DeData = () => { const [myData, setMyData] = useState(data); const handleInputChanges = (e, qaIndex, childIndex) => { const { name, value } = e.target; // 深度复制根数组和第一层对象,避免直接修改原状态 const newMyData = [...myData]; const rootItem = { ...newMyData[0] }; if (childIndex === undefined) { // 修改的是第一层配置,同步更新所有子节点对应下标的配置 const newRootQa = [...rootItem.questionsAnswers]; newRootQa[qaIndex] = { ...newRootQa[qaIndex], [name]: value }; rootItem.questionsAnswers = newRootQa; // 遍历更新所有子节点的对应qa rootItem.children = rootItem.children.map(child => { const newChildQa = [...child.questionsAnswers]; newChildQa[qaIndex] = { ...newChildQa[qaIndex], [name]: value }; return { ...child, questionsAnswers: newChildQa }; }); } else { // 修改的是单个子节点的配置,只更新对应子节点 const newChildren = [...rootItem.children]; const targetChild = { ...newChildren[childIndex] }; const newChildQa = [...targetChild.questionsAnswers]; newChildQa[qaIndex] = { ...newChildQa[qaIndex], [name]: value }; targetChild.questionsAnswers = newChildQa; newChildren[childIndex] = targetChild; rootItem.children = newChildren; } newMyData[0] = rootItem; setMyData(newMyData); }; return ( <> <ul> {myData[0].questionsAnswers?.map((qaItem, qaIndex) => ( <input key={qaItem.id} className="InputStyle3" style={{ width: 400, height: 40, marginBottom: 13 }} onChange={(e) => handleInputChanges(e, qaIndex)} type="text" name="name" value={qaItem.name} /> ))} </ul> <ul> {myData[0].children?.map((childItem, childIndex) => ( <React.Fragment key={childItem.name}> <label>{childItem?.name}</label> {childItem?.questionsAnswers?.map((qaItem, qaIndex) => ( <input key={qaItem.id} className="InputStyle3" style={{ width: 400, height: 40, marginBottom: 13 }} onChange={(e) => handleInputChanges(e, qaIndex, childIndex)} type="text" name="name" value={qaItem.name} /> ))} </React.Fragment> ))} </ul> </> ); } export default DeData;
主要修改点
- 回调新增
childIndex可选入参,用于区分修改的是第一层还是对应索引的子节点数据 - 新增同步更新逻辑:修改第一层的问答配置时,会自动同步更新所有子节点对应下标的问答配置,匹配你的需求
- 全量采用不可变更新方式,所有修改都基于副本操作,保证React状态更新能被正确检测
- 修复了原代码将数组转为对象的错误更新写法
- 统一补充了列表渲染的key属性,避免React警告
- 调整了重复的变量命名,避免作用域冲突
内容的提问来源于stack exchange,提问作者brabus
相关产品推荐
相关产品推荐

