修改数组内对象值时出错:对象被篡改且触发TypeError
核心问题1:错误的分类替换逻辑
你在onChangeValue中生成newData时,通过newItem.subCategories.some(x => x.name === item.name)判断要替换的分类,这会导致只要某个分类的子项包含当前点击的item.name,就会把该分类的子数组替换成newSub。如果此时newSub来自错误的父分类(比如第二个分类),就会出现第一个分类的子数组被替换成第二个分类内容的情况。
比如点击vegan时,若传入的index是第二个分类的索引(1),newSub就会是第二个分类的子数组,而第一个分类的子项里包含vegan,所以第一个分类的子数组会被错误替换。
核心问题2:index参数传递错误
调用onChangeValue时传入的index应为当前子项所属父分类的索引,但这里显然传递错误,导致newSub取错了父分类的子数组,引发后续替换错误。
后续报错原因
当第一个分类的子数组被替换成第二个分类的内容后,后续点击three时,可能传入的index超出了data数组的长度(比如index=2),此时data[index]为undefined,访问undefined.subCategories就会抛出TypeError。
修复方案
修正更新逻辑,直接针对指定父分类修改
不需要遍历所有分类匹配,直接通过父分类索引定位目标分类,更新其子数组即可,避免错误替换其他分类:const onChangeValue = (item, parentIndex, newValue) => { // 复制原数组,避免直接修改状态 const updatedData = [...data]; // 获取目标父分类 const targetCategory = updatedData[parentIndex]; // 更新子分类的value targetCategory.subCategories = targetCategory.subCategories.map(subCat => { // 使用严格相等匹配,避免部分匹配的风险 if (subCat.name === item.name) { return { ...subCat, value: newValue }; } return subCat; }); setData(updatedData); }确保index参数传递正确
渲染子项时,传入的parentIndex必须是当前子项所属父分类的索引:- 渲染第一个分类(Diet)的子项时,传入
0 - 渲染第二个分类(Daily Exercise in Hours)的子项时,传入
1
- 渲染第一个分类(Diet)的子项时,传入
示例渲染逻辑:
{data.map((category, parentIndex) => ( <div key={category.category}> <h3>{category.category}</h3> {category.subCategories.map(item => ( <button key={item.name} onClick={() => onChangeValue(item, parentIndex, !item.value)} > {item.name}: {item.value.toString()} </button> ))} </div> ))}
这样就能保证每次点击子项时,只会更新其所属父分类的子数组,不会出现跨分类替换的问题,后续也不会触发undefined错误。
内容的提问来源于stack exchange,提问作者pelotador.1

