调用getWithQuery时修改NgRx Data的additionalCollectionState的count无变化如何解决
问题原因
- 你自定义的
addCountaction无法被NgRx Data的内置集合reducer识别:NgRx Data的additionalCollectionState属性有专属的状态更新逻辑,普通自定义action如果没有额外编写reducer关联到对应集合的状态树,修改不会生效。 - 状态修改时机不对:你在
pipe的tap操作里提前触发修改,后续NgRx Data收到getWithQuery返回的实体数据后,会自动触发QUERY_SUCCESS内置action,默认的reducer逻辑会重置对应集合的状态,覆盖你之前的修改。 - 未提前注册
additionalCollectionState:如果没有在实体元数据(EntityMetadata)中提前声明count属性的默认值,NgRx Data不会将该字段纳入对应集合的状态管理范围。
解决方案
步骤1:注册additionalCollectionState
首先在实体元数据配置中为CourseLevel集合声明count的默认值:
// 实体元数据配置文件 import { EntityMetadataMap } from '@ngrx/data'; export const entityMetadata: EntityMetadataMap = { CourseLevel: { additionalCollectionState: { count: 0 // 声明count属性的初始值 } } };
步骤2:使用NgRx Data内置API修改附加状态
不要使用自定义的addCount action,改用NgRx Data提供的内置方法更新附加状态。可以直接用你已经注入的EntityCacheDispatcher提供的setAdditionalCollectionState方法,同时调整状态更新的触发时机,避免被默认逻辑覆盖。这里推荐两种实现方式:
方式1:通过Effects监听查询成功事件触发修改
// course-level.effects.ts @Injectable() export class CourseLevelEffects { loadCourseLevelSuccess$ = createEffect(() => this.actions$.pipe( ofEntityOp(EntityOp.QUERY_SUCCESS, 'CourseLevel'), tap((action) => { // 从action的payload中获取接口返回的count const count = action.payload?.count; this.dispatcher.setAdditionalCollectionState( 'CourseLevel', { count } ); }) ), { dispatch: false } ); constructor( private actions$: Actions, private dispatcher: EntityCacheDispatcher ) {} }
对应调整你的DataService代码,把count透传到QUERY_SUCCESS的payload中:
getWithQuery(params: QueryParams): Observable<any> { return this.http .get<any>(environment.apiUrl + `CourseLevel`, { params }) .pipe( map((res) => { // 把count挂载到返回的实体数组上,方便effects获取 const entities = res.data; (entities as any).count = res.count; return entities; }) ); }
方式2:直接在DataService中手动处理整个数据更新流程
如果不想加Effects,可以直接关闭NgRx Data的默认成功处理,手动触发实体保存和附加状态修改:
getWithQuery(params: QueryParams): Observable<any> { return this.http .get<any>(environment.apiUrl + `CourseLevel`, { params }) .pipe( tap((res) => { // 手动保存查询到的实体数据 this.dispatcher.querySuccess('CourseLevel', res.data, params); // 手动更新附加状态的count this.dispatcher.setAdditionalCollectionState('CourseLevel', { count: res.count }); }), map((res) => res.data), catchError(err => { this.dispatcher.queryError('CourseLevel', err, params); return throwError(() => err); }) ); }
注意如果用方式2,需要确认手动分发的action不会和NgRx Data的默认处理逻辑冲突。
内容的提问来源于stack exchange,提问作者Murad Agha
相关产品推荐
相关产品推荐

