Как сбросить все состояния ngrx / store?
Я использую Angular 2 с ngrx / store. Я хочу сбросить все состояния магазина, когда пользователь dispatch USER_LOGOUT
.
Я прочитал ответ Дана Абрамова как сбросить состояние магазина Redux?, но я не понял, как писать rootReducer
правильно и куда положить его при использовании ngrx / store.
или есть ли другой способ справиться с этим в ngrx / store?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)({
router: routerReducer,
foo: fooReducer,
bar: barReducer
})
)
]);
4 ответов
этот ответ специфичен для ngrx версии 2. Вопрос другой, более свежий ответ это объясняет, как то же самое можно сделать с ngrx версии 4.
compose
строит ngrx корень редуктор.
аргументы, переданные 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. Насколько я понимаю, все действия проходят через метаредукторы, прежде чем их передадут редукторам функций. Это дает нам возможность сначала изменить / сбросить состояние.
вот пример.
Это моя функция metareducer: если действие имеет тип LOGOUT, состояние повторно инициализируется.
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
ниже вы видите, как metareducer настроено вместе с редукторами функций. Если существует более 1 метаредуктора, то они оцениваются справа налево
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 }),
...
]
это не совсем ответ, но комментарии не позволяют мне его правильно отформатировать. Чтобы добавить к тому, что сказал картант, если вы настраиваете свои типы следующим образом:
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);