React Hooks中如何正确向嵌套数组添加元素?当前写法生成错误结构
React Hooks嵌套数组添加元素错误修复
问题场景
原本的state是一个包含对象的数组,对象内有ages数组,点击按钮想向ages中添加随机生成的age值,但操作后state结构完全错误:
原state定义:
const [state, setState] = useState([ { name: "test", lname: "lname", ages: [ { age: 30 } ] } ]);
错误的点击事件代码:
const randomAge = () => { let rg = ((Math.random() * 1000) / 10).toFixed(); setState({ ...state, ages: { ...state.ages, age: rg } }); };
错误输出:
{ "0": { "name": "test", "lname": "lname", "ages": [ { "age": 30 } ] }, "ages": { "rg": "34" } }
期望输出:
[ { "name": "test", "lname": "lname", "ages": [ { "age": 30 }, { "age": 50 }, { "age": 60 } ] } ]
错误原因
- 原state是数组类型,但
setState({ ...state })把数组展开成了对象(索引作为键),直接改变了state的整体结构。 - 错误地给state根节点添加
ages属性,而不是更新数组中第一个对象的ages数组;且把ages当成对象处理,用对象展开语法,而ages本质是数组,应该用数组展开来添加元素。
正确代码
使用函数式更新确保拿到最新state,同时保持数组结构,正确更新嵌套的ages数组:
const randomAge = () => { let rg = ((Math.random() * 1000) / 10).toFixed(); setState(prevState => { // 遍历原数组(这里只有一个元素),复制对象并更新ages return prevState.map(item => ({ ...item, ages: [...item.ages, { age: Number(rg) }] // 转成数字保持类型一致 })); }); };
如果确定数组中只有一个元素,也可以简化写法:
const randomAge = () => { let rg = ((Math.random() * 1000) / 10).toFixed(); setState(prevState => [ { ...prevState[0], ages: [...prevState[0].ages, { age: Number(rg) }] } ]); };
关键说明
- 函数式更新
setState(prevState => ...):避免闭包导致的state过期问题,确保基于最新状态修改。 - 保持state结构:始终返回数组,和初始state的结构一致。
- 数组更新:用
[...原数组, 新元素]的方式创建新数组,符合React不可变更新的原则,避免直接修改原state。 - 类型统一:
toFixed()返回字符串,转成Number后和原age的数字类型匹配。
内容的提问来源于stack exchange,提问作者vivek singh
相关产品推荐
相关产品推荐

