簡體   English   中英

如何重置ngrx/store的所有狀態?

[英]How to reset all states of ngrx/store?

我正在使用 Angular 2 和ngrx/store 我想在用戶調度USER_LOGOUT時重置整個商店狀態。

我閱讀了 Dan Abramov 關於如何重置 Redux 商店的 state 的回答? ,但是我沒有弄清楚如何正確編寫rootReducer以及在使用ngrx/store時將它放在哪里。

或者有沒有其他方法可以在ngrx/store 中處理這個問題?

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

在ngrx / store 4.x中,這可以通過metareducers來完成。 據我了解,所有操作都會在傳遞給功能減少器之前通過元數據刪除器。 這使我們有機會首先更改/重置狀態。

這是一個例子。

這是我的metareducer函數:如果操作是LOGOUT類型,則重新初始化狀態。

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

下面您將看到如何配置metareducer以及功能減少器。 如果有超過1個metareducer,那么它們將從右到左進行評估

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'])
});

這個答案特定於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
    })
  )
]);

請注意,這將重置所有商店的狀態 - 包括router 如果這不是你想要的,你可以調整一下這個例子。

隨着NgModule的引入,bootstrapping已經改變了,但你仍然將組合的reducer傳遞給provideStore

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

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

使用@ 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 }),
   ...
]

這不是一個真正的答案,但評論不會讓我正確格式化。 要添加到cartant所說的內容,如果要設置類型如下:

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

這是您應該使用的長描述。 此外,如果您將根減速器rootReducerrootReducer而不僅僅是reducer那么您也可以更改它。 以下是一個經編輯的示例:

(我在root減速機中保留了這個功能)

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);

[2022 年更新]

這篇博文就像 Angular 14 的魅力一樣,非常容易實現。 您可以使用任何操作來重置存儲。 https://www.purcellyoon.com/insights/articles/angular-ngrx-8-reset-state-using-meta-reducer

在 actions.ts 中定義注銷操作

import { createAction, props } from '@ngrx/store';

export const logoutSuccess = createAction('[Authentication] Logout Success');

在 reducers.ts 中定義你的 MetaReducer

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

import * as AuthActions from './actions';

export const reducers: ActionReducerMap<State> = {
    [featureKey1]: reducer1,
    [featureKey2]: reducer2,
    //...

    }

export const logout = (reducer: ActionReducer<any>): ActionReducer<any> => {
  return (state, action) => {
    if (action !== null && action.type === AuthActions.logoutSuccess.type) {
      return reducer(undefined, { type: INIT });
    }
    return reducer(state, action);
  };
};

export const metaReducers: MetaReducer[] = [logout];

app.store.module.ts

import { metaReducers, reducers } from '../store/reducers';

@NgModule({
  imports: [
    StoreModule.forRoot(reducers, {
      metaReducers,
      runtimeChecks: {
        strictStateImmutability: true,
        strictActionImmutability: true
      }
    }),

現在在組件中調度您的操作

this.store.dispatch(logout());

實際上,調度注銷成功操作,以便用戶注銷並重置存儲。

logout$ = createEffect(() => this.actions$.pipe(
      ofType(Actions.logout),
      mergeMap((action) =>
        this.apiService.logout().pipe(
          map((user: User) => Actions.logoutSuccess()),
          catchError((error) => of(Actions.logoutFailure({ error })))
        )
      )
    ));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM