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

Hon*_*iao 20 typescript ngrx angular

我正在使用Angular 2和ngrx/store.我想在用户调度时重置整个商店状态USER_LOGOUT.

我读了Dan Abramov关于如何重置Redux商店状态的答案,但我没有弄清楚如何rootReducer正确编写以及在使用ngrx/store时将其放在何处.

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

bootstrap(App, [
    provideStore(
      compose(
        storeFreeze,
        storeLogger(),
        combineReducers
      )({
        router: routerReducer,
        foo: fooReducer,
        bar: barReducer
      })
    )
  ]);
Run Code Online (Sandbox Code Playgroud)

Dav*_*lté 35

在ngrx/store 4.x中,这可以通过metareducers来完成.据我了解,所有操作都会在传递给功能减少器之前通过元数据删除器.这使我们有机会首先更改/重置状态.

这是一个例子.

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

function logout(reducer) {
  return function (state, action) {
    return reducer(action.type === LOGOUT ? undefined : state, action);
  }
}
Run Code Online (Sandbox Code Playgroud)

下面您将看到如何配置metareducer以及功能减少器.如果有超过1个metareducer,那么它们将从右到左进行评估

StoreModule.forRoot({rooms: roomReducer, user: userReducer}, {metaReducers: [logout]})
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这对于 Angular 8 和 Ngrx-8 仍然完全有效。 (2认同)

car*_*ant 15

这个答案特定于ngrx版本2.该问题还有另一个更新的答案,解释了如何使用ngrx版本4完成相同的操作.


compose构建ngrx 根减速器.

传递给的参数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
    })
  )
]);
Run Code Online (Sandbox Code Playgroud)

请注意,这将重置所有商店的状态 - 包括router.如果这不是你想要的,你可以调整一下这个例子.

随着NgModule引导的引入已经改变,但您仍然将组合的reducer传递给provideStore:

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

@NgModule({
    ...
    imports: [
        ...
        StoreModule.provideStore(compose(...))
    ],
    ...
Run Code Online (Sandbox Code Playgroud)


Lim*_*nis 14

使用@ 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];
Run Code Online (Sandbox Code Playgroud)

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

export const imports: any = [
   StoreModule.forRoot(rootReducer, { metaReducers }),
   ...
]
Run Code Online (Sandbox Code Playgroud)