[英]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'),
....
}
這是您應該使用的長描述。 此外,如果您將根減速器rootReducer
為rootReducer
而不僅僅是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.