首页 > 解决方案 > Ngrx 重置商店后,组件调度一个动作

问题描述

我已经为我的应用程序实现了商店。注销后我想重置商店。但有一个问题。

假设我有以下状态:

subjects: {
    subjectsLoaded: true
}

在组件中,我订阅了这样的商店:

 this.store.pipe(
        select(areSubjectsLoaded),
         tap((subjectsLoaded) => {
             if (!subjectsLoaded) {
                 this.store.dispatch(loadSubjects());
                 console.log('Dispatching Subjects because they are not Loaded');
             }
         }),
         filter(subjectsLoaded => subjectsLoaded),
         takeUntil(this.unsubscribe$)
     ).subscribe();

注销并重置商店后,它将如下所示:

 subjects: {
    subjectsLoaded: false
}

由于我订阅了组件中的更改,因此将进行操作调度。但我不知道如何防止这种情况。我也是takeUntil 为了在组件销毁后不接收数据

有一个小演示:

在此处输入图像描述

为了清除我正在使用 metaReducers 的商店:

export const metaReducers: MetaReducer<AppState>[] = [clearState];

export function clearState(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
  return (state: AppState, action: Action): AppState => {
    if (action.type === '[Toolbar] User Logout') {
      console.log('Clear state: ',state);
      state = undefined;
    }
    return reducer(state, action);
  };
}

标签: angularreduxngrx

解决方案


我认为您必须使用除 之外的其他内容undefined,因为正如您所见,您无法再区分“状态尚未初始化”和“状态必须重置”。

您可以使用 asymbol来区分这些状态

export const RESET_STATE = Symbol('reset state');
// your meta-reducer
state = RESET_STATE;

return state;

现在您可以通过这种方式识别它们:

this.store.pipe(
  filter(state => state !== RESET_STATE),
  select(areSubjectsLoaded),
  /* ... */
)

如果您不想重复自己,您可以根据该逻辑创建一个选择器,并在您的其他选择器中使用它。


推荐阅读