Ngrx:无法分配给对象“[Object]”的只读属性“Property”

inf*_*dev 14 javascript javascript-objects typescript ngrx angular

我正在使用 ngrx 商店。

在我的状态下,我必须物品

export interface ISchedulesState {
  schedulings: ISchedules;
  actualTrips: ISchedule[];
}
Run Code Online (Sandbox Code Playgroud)

这是我的接口

export interface ISchedules {
  [key: string]: ISchedule[];
}

export interface ISchedule {
  dest: number;
  data: string
}
Run Code Online (Sandbox Code Playgroud)

在减速器中我更新 actualTrips

export const SchedulingReducers = (
  state = initialSchedulingState,
  action: SchedulesAction
): ISchedulesState => {
  switch (action.type) {
    case ESchedulesActions.GetSchedulesByDate: {
      return {
        ...state
      };
    }
    case ESchedulesActions.GetSchedulesByDateSuccess: {
      return {
        ...state,
        schedulings: action.payload
      };
    }
    case ESchedulesActions.GetSchedulesByTime: {
      let time = action.payload;
      state.actualTrips = [...(state.schedulings[time] || [])]; // if not data return empty array
      return state;
    }
    default:
      return state;
  }
};
Run Code Online (Sandbox Code Playgroud)

但实际上我得到了一个错误

错误类型错误:无法分配给对象“[object Object]”的只读属性“actualTrips”

kve*_*tis 16

Redux 模式的基本原则是状态及其部分的不变性,因为它让我们可以仅通过对象引用而不是比较整个对象来检测变化。

在您的减速器中,您不能直接分配状态 ( state.actualTrips =)的属性,因为更改检测器(和选择器)不会将其检测为已更改。

要修改状态,请返回带有新修改的状态副本。

  const time = action.payload;
  return {
      ...state,
      actualTrips: [...(state.schedulings[time] || [])]
  }
Run Code Online (Sandbox Code Playgroud)

  • 但超级烦人的事情是您想要修改例如嵌套对象(根对象中的数组中的数组)。据我所知,我必须对整个对象树进行深度复制,然后在存储中更新它,这当然会消耗内存。如何避免这样的事情呢? (2认同)

小智 6

当我更改模板中的输入值时,发生了该错误。我使用的是Angular11 + NGRX11 ,所以我知道我从store更改了一个值,这是我的修复:

前:

 this.store.dispatch(new Actions.LoginUser({ user: this.user }));
Run Code Online (Sandbox Code Playgroud)

后:

 const clone = { 
  user: Object.assign({}, this.user) 
 };
 this.store.dispatch(new Actions.LoginUser(clone));
Run Code Online (Sandbox Code Playgroud)


小智 5

如果要更改 state.actualTrips = myNewValue 是不允许的,因为有严格的设置。所以一种方法可能是 clonedeep 并返回对象,比如 newState = cloneOfState ... 我没有测试它。所以我在 app.module 中为 Store 更改了设置。我的示例:将 strictStateImmutability 更改为 false(此处为完整文档:https ://ngrx.io/guide/store/configuration/runtime-checks )

    StoreModule.forRoot(ROOT_REDUCERS_TOKEN, {
        metaReducers,
        runtimeChecks: {
            // strictStateImmutability and strictActionImmutability are enabled by default
            strictStateSerializability: true,
            strictActionSerializability: true,
            strictActionWithinNgZone: true,
            strictActionTypeUniqueness: true,
            // if you want to change complexe objects and that we have. We need to disable these settings
            // change strictStateImmutability, strictActionImmutability
            strictStateImmutability: false, // set this to false
            strictActionImmutability: true,
        },
    }),
Run Code Online (Sandbox Code Playgroud)