You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NgRx/RxJS中Action传入Prop变为不可变的问题排查与解决

问题原因

NgRx 自9.0版本起,默认开启strictActionImmutability(严格Action不可变校验)运行时检查规则:所有被传入Action的props属性,无论后续是否经过Reducer处理、是否被存入Store,都会被NgRx做深度冻结处理,变为只读的不可变状态。
由于JavaScript中对象为引用传递,当你直接把本地持有的this.noteRequest实例作为props传入Action执行dispatch时,NgRx冻结Action属性的操作会直接作用在原对象引用上,导致本地持有的请求模型实例也被冻结,后续修改分页、搜索条件等属性时就会出现无法赋值的异常。这也是为什么你在dispatch时传入深克隆副本后功能恢复正常——克隆出的新对象被冻结不会影响你本地持有的原可变对象。

解决方案

你可以根据项目实际情况选择以下方案处理:

  • 优先推荐:Dispatch时传入请求对象的副本,完全符合NgRx的不可变数据流设计。如果请求模型没有嵌套属性,使用浅克隆即可;存在多层嵌套属性时使用深克隆,避免原对象被冻结。
    public getNotes(){    
      this.noteStore.dispatch(
        NotesActions.loadNotes({getNotesRequestModel: _.cloneDeep(this.noteRequest)})
      );
    }
    
  • 按需调整运行时校验配置(不推荐生产环境使用):如果你确认项目代码不会出现误改Action/State的逻辑,可以在根模块导入Store时关闭严格Action不可变校验,该操作会丢失NgRx提供的不可变异常告警,容易引发难以排查的数据流问题。
    @NgModule({
    declarations: [
      AppComponent,
    ],
    imports: [
      BrowserModule,
      StoreModule.forRoot(reducers, {
        metaReducers,
        runtimeChecks: {
          strictStateImmutability: true,
          strictActionImmutability: false // 关闭Action不可变严格校验
        }
      }),
      // 其余业务模块导入
    ],
    providers: [],
    bootstrap: [AppComponent]
    })
    
  • 优化参数生成逻辑:不复用同一个可变对象存储请求参数,每次发起请求时基于当前的分页、搜索条件重新生成GetNotesRequestModel实例,从根源上避免持有被冻结对象引用后修改的操作。

提示:NgRx默认开启Action不可变校验的核心目的是避免开发者在数据流链路外随意修改Action携带的状态,导致难以追踪的状态不一致问题,非特殊场景不建议关闭该校验规则。

内容的提问来源于stack exchange,提问作者adova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:15:38