Ngrx / rxjs动作道具变成不可变的



我发现我发送到动作的道具(例如:带搜索条件的类模型发送到API)正在变得不可变,我不能修改该类的属性。

现在,我明白了reducer/store对象是不可变的,但是这个类在任何时候都不会接触到reducer或进入store。

我已经使用Ngrx好几年了,我只是遇到了一些我没有意识到的行为,或者是新的。也许我在其他地方完全遗漏了一些东西,但任何见解都是值得赞赏的。

采取下面这个简单的动作,它在一个类prop中代表一个请求:

export const loadNotes= createAction('[Notes] Load Notes',
props<{ getNotesRequestModel: GetNotesRequestModel }>()
);

然后触发此操作的效果,以调用加载注释的服务:

loadNote$ = createEffect(() =>
this.actions$.pipe(
ofType(NoteActions.loadNotes),
switchMap((action) =>
from(
this.noteService.getNotesList(action.getNotesRequestModel)
).pipe(
map((response) => {
return NoteActions.loadNotesSuccess({ response });
}),
catchError((error) => {
return of(NoteActions.loadNoteFail());
})
)
)
)
);

最后,一个reducer处理在状态中存储响应:

on(NoteActions.loadNotesSuccess,(state: INoteState, { response }) => ({
...state,
noteResponse: response,
})),

这一切都工作得很好,除了在第一次调用动作之后,本地getNotesRequestModel变量现在是不可变的,这阻止了我更改属性,如分页等,以便后续调用API。

但是,如果我修改调度来克隆请求对象,它会工作得很好。

public getNotes(){    
this.noteStore.dispatch(
NotesActions.loadNotes({getNotesRequestModel: _.cloneDeep(this.noteRequest)})
);
}

更新:

研究Ngrx版本历史表明,从版本8.6到9,严格的行动不变性是默认设置为true。我已经忘记了这一点,也忘记了为什么我以前没有经历过这种行为。

如果需要,严格不变性可以通过StoreModule设置控制,如下所示:

@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
StoreModule.forRoot(reducers, {
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
.....
],
providers: [],
bootstrap: [AppComponent]
})

道具将被发送给动作,所以对象被ngrx标记为只读,这样在你发送事件到它被处理之间,动作的值不会改变。

当你传递一个对象的引用时,整个对象是不可变的。

最新更新