mwi*_*son 1 rxjs typescript angular
我的商店中目前有一组对象。给定传入的对象,我想更新该对象的单个属性。
状态
export interface ApplicationState {
...
allNavGroups: INavGroup[] | null;
}
Run Code Online (Sandbox Code Playgroud)
减速器
on(ApplicationActions.toggleCollapseNavGroup, (state, group: INavGroup ) => {
const navGroup = state.allNavGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state };
})
Run Code Online (Sandbox Code Playgroud)
但是,这会导致:
错误类型错误:无法添加折叠的属性,对象不可扩展
在看到这个 GitHub 问题后,我尝试这样做,但同样的问题:
const navGroups = [ ...state.allNavGroups ];
const navGroup = navGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state, allNavGroups: navGroups };
Run Code Online (Sandbox Code Playgroud)
我已经看到了一些关于更新数组中对象的不同方式的线程,但似乎有很多代码可以做一件简单的事情。在其他线程中,我看到您必须替换对象,而不是更新它。当我尝试这样做时,它似乎有效。但是,这需要添加更多逻辑以确保数组的顺序与以前相同。
是否有一种简单的方法可以仅更新Store.
更新如果我遍历数组中的每个对象并对其进行解构,它就可以工作。这似乎是一个黑客。
const navGroups = state.allNavGroups.map(g => ({ ...g }));
const navGroup = navGroups.find( g => g.groupId === group.groupId);
navGroup.collapsed = !navGroup.collapsed;
return { ...state, allNavGroups: navGroups };
Run Code Online (Sandbox Code Playgroud)
根据我的理解,即使它们相互嵌套,您也必须为通过引用存储的属性(数组和对象)不可变地改变状态。
所以对于你的情况,我会这样做:
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;
}
}
})
};
Run Code Online (Sandbox Code Playgroud)
1 - 地图创建了一个新数组(在 ram 中的不同位置),因此我们负责以不可变的方式更新数组。
2 - 我们正在传播对象并创建一个副本(在 ram 中的不同位置),因此我们正在以不可变的方式更新内部对象。
3 - 我们正在使用第二个映射创建一个新数组并更改对象的键之一。可能没有必要navGroup在倒塌的财产上进行传播和固定,但我们仍然这样做了。这可能是您可以尝试的东西。
至于为什么这样做,我相信它有助于提高性能并有助于时间旅行调试。如果您稍后在应用程序中以可变方式更改数组中对象的此属性,则通过 devtools 中的 redux 存储将使之前的所有状态都具有此更改,这是不准确的(内存泄漏)。