如何重置ngrx/store的所有状态?

Posted

技术标签:

【中文标题】如何重置ngrx/store的所有状态?【英文标题】:How to reset all states of ngrx/store? 【发布时间】:2017-01-12 09:26:01 【问题描述】:

我正在使用带有ngrx/store 的Angular 2。我想在用户发送 USER_LOGOUT 时重置整个商店状态。

我阅读了 Dan Abramov 对 How to reset the state of a Redux store? 的回答,但我不知道如何正确编写 rootReducer 以及在使用 ngrx/store 时将其放在何处。

或者在ngrx/store中有没有其他方法可以处理这个问题?

bootstrap(App, [
    provideStore(
      compose(
        storeFreeze,
        storeLogger(),
        combineReducers
      )(
        router: routerReducer,
        foo: fooReducer,
        bar: barReducer
      )
    )
  ]);

【问题讨论】:

【参考方案1】:

在 ngrx/store 4.x 中,这可以通过 Meta-reducers 来完成。据我了解,所有动作都经过元缩减器,然后才移交给特征缩减器。这让我们有机会首先更改/重置状态。

这是一个例子。

这是我的 metareducer 函数:如果动作是 LOGOUT 类型,则重新初始化状态。

function logout(reducer) 
  return function (state, action) 
    return reducer(action.type === LOGOUT ? undefined : state, action);
  

您将在下面看到如何配置 metareducer 以及 feature reducer。如果 metareducer 超过 1 个,则从右到左计算它们

StoreModule.forRoot(rooms: roomReducer, user: userReducer, metaReducers: [logout])

最后,我还有一个@effect 导航到登录页面

@Effect(dispatch: false) logout: Observable<Action> = 
this.actions$.ofType(LOGOUT)
  .do(() => 
    // ... some more stuff here ...
    this.router.navigate(['/login page'])
);

【讨论】:

这应该是公认的答案,因为现在 4.x 有一些变化。 这对于 Angular 8 和 Ngrx-8 仍然完全有效。【参考方案2】:

此答案特定于 ngrx 版本 2。问题有 another, more recent answer,它解释了如何使用 ngrx 版本 4 完成相同的操作。


compose 构建 ngrx root reducer

传递给compose 的参数是返回reducer 的函数——由reducer 组成,它们本身作为参数传递。您可以像这样编写商店的重置:

import  compose  from "@ngrx/core/compose";

...

bootstrap(App, [
  provideStore(
    compose(
      storeFreeze,
      storeLogger(),
      (reducer: Function) => 
        return function(state, action) 
          if (action.type === 'USER_LOGOUT') 
            state = undefined;
          
          return reducer(state, action);
        ;
      ,
      combineReducers
    )(
      router: routerReducer,
      foo: fooReducer,
      bar: barReducer
    )
  )
]);

请注意,这将重置商店的所有状态 - 包括 router。如果这不是您想要的,您可以调整示例。

随着NgModule 的引入,引导发生了变化,但您仍然将组合的reducer 传递给provideStore

import  compose  from "@ngrx/core/compose";
import  StoreModule  from "@ngrx/store";

@NgModule(
    ...
    imports: [
        ...
        StoreModule.provideStore(compose(...))
    ],
    ...

【讨论】:

如何在当前版本的ngrx中做到这一点? @Daskus 你将组合reducer 传递给StoreModule.provideStore。查看更新后的答案。 @cartant 如何使用forRootforFeature 在最新的ngrx 版本上执行此操作?我在 angularindepth.com 上关注你,我希望能有一篇关于此的文章。 @AndreaM16 请参阅下面 David Bulté 的回答。【参考方案3】:

与@ngrx/store": "^4.0.3" 这略有不同,因为有小的变化,所以我的'清除状态'看起来像这样

import  ActionReducerMap  from '@ngrx/store';
import  ActionReducer, MetaReducer  from '@ngrx/store';

export const rootReducer: ActionReducerMap<StoreStates> = 
  points: pointsReducer,
  ...
;

export function clearState(reducer: ActionReducer<StoreStates>): ActionReducer<StoreStates> 
  return function(state: StoreStates, action: Action): StoreStates 
    if (action.type === 'CLEAR_STATE') 
      state = undefined;
    
    return reducer(state, action);
  ;

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

import  StoreModule  from '@ngrx/store';
import  metaReducers, rootReducer  from '../root.reducer';

export const imports: any = [
   StoreModule.forRoot(rootReducer,  metaReducers ),
   ...
]

【讨论】:

当应用程序被组织成模块(延迟加载)并且每个模块都有自己的功能状态时,这将如何工作? 它也适用于延迟加载,我的意思是我的所有功能模块都延迟加载,但服务和商店位于我放入应用程序模块的共享模块中 顺便说一句,我的 CLEAR_STATE 操作是 LOGOUT ACTION)【参考方案4】:

这不是一个真正的答案,但 cmets 不会让我正确格式化它。补充一下 carant 所说的,如果您要这样设置类型:

export const ActionTypes = 
  LOGOUT:  type('[Environment] Logout of portal'),
  ....

这是您应该使用的长描述。此外,如果您将根减速器命名为 rootReducer 而不仅仅是 reducer,那么您也可以更改它。以下是经过编辑的示例:

(我将这个函数留在了我的根减速器中)

const developmentReducer: ActionReducer<State> = compose(...DEV_REDUCERS,
(rootReducer: Function) => 
    return function(state, action) 
      if (action.type === '[Environment] Logout of portal') 
        state = undefined;
      
      return rootReducer(state, action);
    ;
  , combineReducers)(reducers);

【讨论】:

你如何使用 productionReducer 做到这一点?

以上是关于如何重置ngrx/store的所有状态?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 状态管理 - 存储还是有状态服务? [关闭]

在 @ngrx/store 4.0 中提供 root reducer

NativeScript + ngrx 存储 + 远程开发工具

如何重置包含所有可传递状态的反应组件?

安装@ngrx/store 时如何清除错误?

将 ngrx/Store 集成到现有的 Angular 项目中