web-dev-qa-db-ja.com

ngrx / storeのすべての状態をリセットする方法は?

Angular 2 with ngrx/store を使用しています。ユーザーがUSER_LOGOUT

Reduxストアの状態をリセットする方法 のダンアブラモフの答えを読みましたが、rootReducerを正しく書く方法とngrxを使用するときにどこに置くかを知りませんでした/お店。

または、ngrx/storeでこれを処理する他の方法はありますか?

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

この回答はngrxバージョン2に固有のものです。質問には 別の、より最近の回答 があり、これはngrxバージョン4でも同じことができることを説明しています。


composeは、ngrxroot reducerを構築します。

composeに渡される引数は、リデューサーを返す関数です。リデューサーから構成され、引数自体が引数として渡されます。次のように、ストアのリセットを作成できます。

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の導入により、ブートストラップは変更されましたが、合成されたレデューサーをprovideStoreに渡します:

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

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

Ngrx/store 4.xでは、これは metareducers で実現できます。私が理解しているように、すべてのアクションはメタリデューサーを通過してから機能リデューサーに渡されます。これにより、最初に状態を変更/リセットする機会が与えられます。

以下に例を示します。

これが私のメタリデューサー機能です。アクションがタイプLOGOUTの場合、状態は再初期化されます。

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

以下に、機能削減機能とともにmetareducerがどのように構成されているかを示します。複数の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'])
});
33
David Bulté

「@ 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 }),
   ...
]
14
Limarenko Denis

これは実際には答えではありませんが、コメントでは正しくフォーマットできません。次のようにタイプを設定している場合、cartantが言ったことに追加します。

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