Я использую Angular 2 с ngrx / store. Я хочу сбросить все состояния магазина при отправке пользователем USER_LOGOUT
.
Я прочитал ответ Дэна Абрамова о Как сбросить состояние Redux store?, но я не понял, как правильно написать 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(...))
],
...
На самом деле это не ответ, но комментарии не позволяют мне его правильно отформатировать. Чтобы добавить к тому, что сказал картант, если вы настраиваете свои типы следующим образом:
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);
С @ 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 }),
...
]
В ngrx / store 4.x это можно сделать с помощью метаредукторы. Насколько я понимаю, все действия проходят через метаредукторы, прежде чем будут переданы редукторам функций. Это дает нам возможность сначала изменить / сбросить состояние.
Вот пример.
Это моя функция метаредуктора: если действие имеет тип LOGOUT, состояние повторно инициализируется.
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
Ниже вы видите, как настроен метаредуктор вместе с редукторами функций. Если метаредукторов больше 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'])
});
Похожие вопросы
Связанные вопросы
Новые вопросы
angular
Вопросы об Angular (не путать с AngularJS), веб-фреймворке от Google. Используйте этот тег для вопросов Angular, которые не относятся к отдельной версии. Для более старой веб-инфраструктуры AngularJS (1.x) используйте тег AngularJS.