如何优雅重置NGRX中公司与员工模块的Feature Reducer状态?
刚好之前处理过类似的NgRx状态重置场景,针对你这种多个feature reducer复用相同子reducer的情况,有几种简洁优雅的方案可以参考:
先贴出你给出的当前代码作为参考:
fromCompany = { list:listReducer, growth:growthReducer } fromEmployee = { list:listReducer, growth:growthReducer } StoreModule.forFeature('company',fromCompany); StoreModule.forFeature('employee',fromEmployee);
方案1:全局统一重置所有Feature状态
如果需要一次性重置所有feature的状态,利用NgRx的**元reducer(Meta Reducer)**是最简洁的方式:
步骤1:定义全局重置动作
import { createAction } from '@ngrx/store'; export const resetAllState = createAction('[App] Reset All Feature States');
步骤2:实现重置元reducer
这个元reducer会拦截所有动作,当触发重置动作时,调用每个reducer的初始状态逻辑(传入undefined作为state,reducer会返回初始值):
import { ActionReducer, MetaReducer } from '@ngrx/store'; import { resetAllState } from './your-actions-file'; export function resetMetaReducer(reducer: ActionReducer<any>): ActionReducer<any> { return (state, action) => { if (action.type === resetAllState.type) { // 传入undefined触发reducer的初始状态逻辑 return reducer(undefined, action); } return reducer(state, action); }; }
步骤3:注册元reducer
在根store模块中注册这个元reducer:
StoreModule.forRoot({}, { metaReducers: [resetMetaReducer] })
之后只要在组件中dispatch这个动作,所有feature的reducer都会回到初始状态:
this.store.dispatch(resetAllState());
方案2:针对单个Feature的精准重置
如果只需要重置某个特定feature(比如只重置company,不影响employee),可以封装一个通用的reducer包装函数,给子reducer添加重置逻辑:
步骤1:定义针对各feature的重置动作
export const resetCompanyState = createAction('[Company] Reset State'); export const resetEmployeeState = createAction('[Employee] Reset State');
步骤2:封装通用的重置包装函数
这个函数可以给任意reducer添加处理指定重置动作的逻辑,避免重复代码:
import { ActionReducer } from '@ngrx/store'; function withReset<T>(reducer: ActionReducer<T>, resetAction: any): ActionReducer<T> { return (state, action) => { if (action.type === resetAction.type) { return reducer(undefined, action); } return reducer(state, action); }; }
步骤3:包装原reducer
在定义feature reducer时,用这个包装函数处理子reducer:
fromCompany = { list: withReset(listReducer, resetCompanyState), growth: withReset(growthReducer, resetCompanyState) }; fromEmployee = { list: withReset(listReducer, resetEmployeeState), growth: withReset(growthReducer, resetEmployeeState) };
这样当你dispatchresetCompanyState()时,只会重置company下的list和growth状态,不会影响employee的状态,非常灵活。
方案3:在单个Reducer中直接处理重置(适合精准控制)
如果你的子reducer是用createReducer创建的,也可以直接在reducer内部添加重置动作的处理逻辑:
import { createReducer, on } from '@ngrx/store'; import { resetCompanyState } from './actions'; // 假设listReducer的初始状态是initialListState export const listReducer = createReducer( initialListState, // 其他业务动作处理... on(resetCompanyState, () => initialListState) );
这种方式适合需要对单个reducer的重置逻辑做特殊处理的场景,但如果多个reducer都需要重置,方案1或2的复用性会更好。
内容的提问来源于stack exchange,提问作者blazehub

