如何在React中修改数组内嵌套对象的属性值?
解决React中嵌套对象数组的状态更新问题
我明白你现在遇到的问题了——之前的代码直接修改了原对象的属性,而且对象展开的写法也有问题,导致状态更新没达到预期。咱们一步步来修正:
问题出在哪?
你之前的代码里有两个关键错误:
- 直接修改了原对象的
item.user.isDeleted = true,这违反了React状态不可变更新的原则,React依赖状态的引用变化来触发重渲染,直接修改原对象不会让组件重新渲染。 - 对象展开的语法错误:
{ ...item, item: (item.user.isDeleted = true) }这里的item:是多余的,你应该更新的是user属性,而不是新增一个item键。
正确的实现方式
我们需要在map遍历中,对匹配到的项进行深度不可变更新:先展开原item对象,再展开它的user对象,然后修改isDeleted为true,其他属性保持不变。
setStaff(prevStaff => { // 用prevState而不是直接用data,避免闭包问题 return prevStaff.map(item => { if (item.id === id) { // 正确嵌套更新,返回新对象 return { ...item, user: { ...item.user, // 展开原user的所有属性 isDeleted: true // 修改目标属性 } }; } return item; // 不匹配的项直接返回 }); });
为什么要这么写?
- 使用
prevStaff作为参数:这是React状态更新的最佳实践,当你的新状态依赖于之前的状态时,一定要用函数式更新,避免闭包导致的旧状态问题。 - 不可变更新:通过展开运算符
...创建新的对象和数组,而不是修改原对象,这样React能检测到状态变化,触发组件重渲染。
完整组件示例
如果是在函数组件里使用,完整的删除逻辑大概是这样:
import { useState } from 'react'; function StaffList() { const [staff, setStaff] = useState([ { id: 2, adminId: 2, roleId: 1, storeId: 1, createdAt: "2021-08-26T16:57:49.000Z", updatedAt: "2021-08-26T16:57:49.000Z", user: { id: 2, empId: 0, firstName: "Test1", lastName: "Test2", email: "test@test3.com", phone: "0900-786013", password: "$2b$10$XPxzZuzKLSl3Rm9YVk7AheZfLbvTNVV0jmo.NR/b0IJuFejW/hCFa", isActive: true, isDeleted: false, createdAt: "2021-08-26T16:57:49.000Z", updatedAt: "2021-08-30T07:34:38.000Z", }, }, ]); const handleDelete = (id) => { setStaff(prevStaff => { return prevStaff.map(item => { if (item.id === id) { return { ...item, user: { ...item.user, isDeleted: true } }; } return item; }); }); }; return ( <div> {staff.map(member => ( <div key={member.id}> <p>{member.user.firstName} {member.user.lastName}</p> <button onClick={() => handleDelete(member.id)}>标记为删除</button> </div> ))} </div> ); } export default StaffList;
这样点击按钮后,对应员工的user.isDeleted就会被正确设置为true,同时组件也会重新渲染展示更新后的状态。
内容的提问来源于stack exchange,提问作者Inzamam Baig
相关产品推荐
相关产品推荐

