我的商店中当前有一系列对象。给定传入的对象,我想更新该对象的单个属性。
州
export interface ApplicationState {
...
allNavGroups: INavGroup[] | null;
}
减速器
on(ApplicationActions.toggleCollapseNavGroup, (state, group: INavGroup ) => {
const navGroup = state.allNavGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state };
})
但是,结果是:
错误TypeError:无法添加折叠的属性,对象不可扩展
看到this GitHub issue后,我尝试通过这种方式进行操作,但存在相同的问题:
const navGroups = [ ...state.allNavGroups ];
const navGroup = navGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state, allNavGroups: navGroups };
我已经看到一些线程以不同的方式更新数组中的对象,但是似乎很多代码可以完成一件简单的事情。在其他线程中,我看到您必须替换对象,而不是 update 对象。当我尝试这样做时,它似乎起作用了。但是,这需要添加更多逻辑以确保数组的顺序与以前相同。
是否有一种简单的方法来仅更新Store
中的对象数组中的对象的属性?
更新如果我遍历数组中的每个对象并对其进行解构,则它将起作用。这似乎是一种hack。
const navGroups = state.allNavGroups.map(g => ({ ...g }));
const navGroup = navGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state, allNavGroups: navGroups };
答案 0 :(得分:4)
根据我的理解,对于引用存储的属性(数组和对象),即使它们彼此嵌套在一起,您也必须对其状态进行不变更改。
对于您的情况,我会这样做:
return {
...state, // 1
allNavGroups: state.allNavGroups.map(navGroup => ({...navGroup})) // 2
.map(navGroup => { // 3
if (navGroup.groupId === group.groupId) {
return {
...navGroup,
collapsed: !navGroup.collapsed,
} else {
return navGroup;
}
}
})
};
1-地图创建了一个新数组(ram中的不同位置),因此我们要以不可变的方式来更新数组。
2-我们正在传播对象并创建一个副本(ram中的不同位置),因此我们要以不变的方式来更新内部对象。
3-我们正在使用第二张地图创建一个新数组,并更改对象的键之一。可能不需要传播navGroup
并固定塌陷的属性,但是我们还是这样做了。这可能是您可以尝试的东西。
关于为什么要这样做,我相信它有助于提高性能,并有助于时间旅行调试。如果稍后要在应用程序中以可变方式更改数组中对象的此属性,则通过devtools中的redux存储将使它像所有先前状态一样具有不准确的更改(内存泄漏)。 / p>