无法添加属性 X,ngrx 9 更新后对象不可扩展

问题描述 投票:0回答:5

我有这样的问题

无法添加属性 X,对象不可扩展

在使用 Ngrx 更新将我的角度项目更新为角度 9 之后。当我将 Ngrxversion 回滚到 8 时,它工作正常。但我还需要使用 angular 9 更新将其更新到 v9。当我将其作为 datasource.data 添加到具有附加属性的材料表中时,就会发生这种情况。我认为额外的属性更改是一个原因。但是我使用 slice 从我们得到的东西创建新数组并像下面这样尝试。

 myDataArray.slice(0)

它也不起作用。

我在这里参考 Ngrx 版本 8 到 9 的更改列表和迁移指南https://ngrx.io/guide/migration/v9

我发现有一个与角度 9 的不变性相关的特殊变化。他们在那里定义了动作、状态和可串行化相关的不变性逻辑。我在这里尝试了他们建议的解决 Ngrx V9 更新问题的方法https://ngrx.io/guide/store/configuration/runtime-checks

但是那些对我不起作用。如果有人能解决这个问题,那真的很有帮助。提前致谢..

错误堆栈跟踪..(我也使用了 matDataFlatner,这就是对象突变发生的地方)

app-error-handler.ts:30 类型错误:无法添加属性级别,对象 不可扩展 在 MatTreeFlattener.defaultFlattenerTransform [as transformFunction] (tree-table-flattener-builder.ts:57) 在 MatTreeFlattener._flattenNode (flat-data-source.ts:58) 在平面数据源.ts:81 在 Array.forEach() 在 MatTreeFlattener._flattenChildren (flat-data-source.ts:78) 在 MatTreeFlattener._flattenNode (flat-data-source.ts:65) 在平面数据源.ts:92 在 Array.forEach() 在 MatTreeFlattener.flattenNodes (flat-data-source.ts:92) 在 MatTreeFlatDataSource.set (flat-data-source.ts:138)

angular redux ngrx angular9
5个回答
27
投票

您应该深度克隆

myDataArray
,因为它是通过选择器从商店中出来的。保持商店中数据的不变性是 redux 模式的重要组成部分,如果您修改
myDataArray
,您将直接在商店中更改数据(取决于您的选择器,它可能是相同的数据=>参考到商店中的数组)。

您可以在尝试对其进行任何更改之前执行

myDataArray = JSON.parse(JSON.stringify(myDataArray))

有更有效的深度克隆对象的方法,例如使用fast-copy

import copy from 'fast-copy';

...

myDataArray = copy(myDataArray);

6
投票

您可以使用 lodash 库中的 cloneDeep 函数来深度克隆对象并避免错误:

import {cloneDeep} from 'lodash';

const clonedData = cloneDeep(myDataArray);

然后,您可以添加属性或所有您想要的克隆数据对象。

问候!


5
投票

我在这里参考 Ngrx 版本 8 到 9 的更改列表和迁移指南

https://ngrx.io/guide/migration/v9

我发现有一个与角度 9 的不变性相关的特殊变化。他们在那里定义了动作、状态和可串行化相关的不变性逻辑。我在这里尝试了他们建议的解决 Ngrx V9 更新问题的方法

https://ngrx.io/guide/store/configuration/runtime-checks

您可以进行以下更改,


@NgModule({
  imports: [
  StoreModule.forRoot(reducers, {
    runtimeChecks: {
      strictStateImmutability: false,
      strictActionImmutability: false,
    },
  }),
 ],
})
export class AppModule {}

@ngrx/store ships with five (5) built-in runtime checks. Try disabled all checks

0
投票

要解决这个问题,我们需要克隆选择器的数据 (

createSelector
)

例子: 在升级 Ngrx 或 Angular 之前,您的代码如下所示:

export const getFrameworkCitationsSuccess = createSelector(getFrameworkState, (state: FrameworkState) => {
  return { frameworkCitations: state.frameworkCitations, filters: state.filters };
});

升级 Ngrx 或 Angular 后做以下更改:

export const getFrameworkCitationsSuccess = createSelector(getFrameworkState, (state: FrameworkState) => {
  return { frameworkCitations: [...state.frameworkCitations], filters: {...state.filters} };
});

SS:


0
投票

由于您需要保持存储中的数据不可变,因此您需要进行深度克隆(其他答案也参考)。 另一种深度克隆对象的方法是使用

structuredClone
方法。 例如:

newLoadList = structuredClone(state.loadsList);

现在

newLoadList
是国家财产的深度复制
loadsList
.

所以,在 reducer 中,您可以使用 newLoadsList 来添加、更新等,然后在状态中返回它。

© www.soinside.com 2019 - 2024. All rights reserved.