对象数组中对象的NgRx更新属性

时间:2020-01-09 22:51:35

标签: angular typescript rxjs

我的商店中当前有一系列对象。给定传入的对象,我想更新该对象的单个属性。

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 };

1 个答案:

答案 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>