如何重置 ngrx 9 的整个商店?

how to reset whole store of ngrx 9?

我已经看到了同样的问题 但是因为我使用 ngrx9 我认为应该有稍微不同的解决方案。我的应用程序模块中的代码和 reducer 如下所示

.....
StoreModule.forRoot(
  reducers,
  {
    metaReducers,
    runtimeChecks: {
      strictStateImmutability: true,
      strictActionImmutability: true
    }
  }),
 ...

而我的进口减速机是

export const reducers: ActionReducerMap<AppState> = {
  [friendsReducer.friendsFeatureKey]: friendsReducer.reducer,
  [authReducer.authFeatureKey]: authReducer.reducer,
  ...
};

export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [] : [];

我的 LOGOUT 操作存储在 auth.actions 中。 那么我应该如何包含 root reducer 来重置所有状态?

只需添加 MetaReducer 即可清除您的状态

export function clearOnLogoutMetaReducer(reducer) {
   return function(state, action) {
      if(action.type === logout.type) {
        return reducer(undefined, action);
      }
      return reducer(state, action);
   }
} 

并将其添加到您的 metareducers 数组

接受的答案是我在 Whosebug 上经常看到的建议,不幸的是,这是你永远不应该做的事情。

问题

如果您使状态可能未定义,您将 运行 遇到几个问题:

  1. 您连接到商店的任何东西(通常只是选择器)都必须以考虑潜在未定义值的方式编写。这会很快变得丑陋,如果犯了错误,可能会导致难以发现错误。

  2. Javascript 如果引擎操纵的对象具有相同的“形状”,则它们的性能会更好。这个主题很复杂,但基本思想是如果对象具有相同的形状,编译器可以使用内联缓存优化操作(这里有一篇关于这个主题的更详细的文章:https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html)。如果您只是通过将其设置为未定义来重置状态,那么状态对象会改变形状,并且您会损失一些性能。在大多数应用程序中,这可能不会产生明显的影响,但需要注意这一点。

  3. 你打破了 redux 设计模式的基本原则之一,即你应该维护一个具有一致接口的集中式状态存储。 redux 设计模式的卖点之一是,如果你遵循它,你就会知道你的应用程序状态将始终具有一致的接口,你永远不必担心状态的某些部分不存在,并且可能导致的问题。这就是为什么 reducer 总是从初始状态对象创建,并且状态属性是在加载其提供程序时急切创建的,而不是动态添加到状态的。如果通过将状态设置为未定义来重置状态,则会失去此保证以及 redux 的一大块价值。

解决方案

要清除商店,您需要分派一个减少为新的初始状态对象的操作。 ngrx/redux 的一大优点是,操作是沿着单个流分派的。这意味着一个特征存储中的缩减器(在你的例子中 'friends')可以监听另一个存储中的动作(在你的例子中 'auth')。因此,在您的 friends.reducer.ts 中执行以下操作:

  import * as AuthActions from 'wherever/your/auth/actions/are';
  
  // Replace this with actual interface
  export interface FriendsState {
    friends: string[];
  }

  // Replace this with actual object
  export const initialFriendsState:FriendsState = {
    friends: [],
  }

  export const reducer = createReducer(
  initialFriendsState,
  on(AuthActions.LOGOUT, (state: FriendsState) => ({...initialFriendsState})),
  on(FriendsActions.GET_FRIENDS (state: FriendsState, {friends}) => ({...state, friends}) 
  //...whatever other reducers you have in your friends store
);