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
})
)
]);
この回答は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(...))
],
...
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'])
});
「@ 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'),
....
}
それはあなたが使うべき長い説明です。また、ルートリデューサーに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);