angular - Wie setzt man alle Zustände von ngrx/store zurück?
Ich verwende Angular 2 mit ngrx/store. Ich möchte den gesamten Store-Zustand zurücksetzen, wenn der Benutzer USER_LOGOUT auslöst.
Ich habe die Antwort von Dan Abramov auf die Frage Wie setzt man den Zustand eines Redux-Stores zurück? gelesen, aber ich habe nicht herausgefunden, wie man rootReducer korrekt schreibt und wo man ihn beim Verwenden von ngrx/store einfügt.
Oder gibt es eine andere Möglichkeit, dies in ngrx/store zu handhaben?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)({
router: routerReducer,
foo: fooReducer,
bar: barReducer
})
)
]);
Antwort #1
In ngrx/store 4.x kann dies mit Meta-Reduzierern erreicht werden. Soweit ich es verstehe, passieren alle Aktionen die Meta-Reduzierer, bevor sie an die Feature-Reduzierer übergeben werden. Dies gibt uns die Möglichkeit, den Zustand zuerst zu ändern/zurückzusetzen.
Hier ist ein Beispiel.
Dies ist meine Metareducer-Funktion: Falls die Aktion vom Typ LOGOUT ist, wird der Zustand neu initialisiert.
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
Unten sehen Sie, wie der Metareducer zusammen mit den Feature-Reducern konfiguriert ist. Sollten mehr als 1 Metareducer vorhanden sein, werden diese von rechts nach links ausgewertet.
StoreModule.forRoot({rooms: roomReducer, user: userReducer}, {metaReducers: [logout]})
Schließlich habe ich auch einen @Effekt, bei dem ich zur Login-Seite navigiere
@Effect({dispatch: false}) logout: Observable<Action> =
this.actions$.ofType(LOGOUT)
.do(() => {
// ... some more stuff here ...
this.router.navigate(['/login page'])
});
Antwort #2
Diese Antwort bezieht sich speziell auf ngrx Version 2. Die Frage hat eine andere, neuere Antwort, die erklärt, wie dasselbe mit ngrx Version 4 gemacht werden kann.
compose erstellt den ngrx Root-Reducer.
Die an compose übergebenen Argumente sind Funktionen, die einen Reducer zurückgeben - zusammengesetzt aus dem Reducer, dem sie selbst als Argument übergeben werden. Sie können das Zurücksetzen Ihres Stores so zusammensetzen:
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
})
)
]);
Beachten Sie, dass dies den gesamten Zustand des Stores zurücksetzt - einschließlich des router. Wenn das nicht das ist, was Sie wollen, könnten Sie das Beispiel anpassen.
Mit der Einführung von NgModule hat sich das Bootstrapping geändert, aber Sie übergeben trotzdem den zusammengesetzten Reducer an provideStore:
import { compose } from "@ngrx/core/compose";
import { StoreModule } from "@ngrx/store";
@NgModule({
...
imports: [
...
StoreModule.provideStore(compose(...))
],
...
Antwort #3
Mit @ngrx/store": "^4.0.3" ist dies etwas anders, weil es kleine Änderungen gibt, also sieht mein 'clear state' so aus
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];
und
import { StoreModule } from '@ngrx/store';
import { metaReducers, rootReducer } from '../root.reducer';
export const imports: any = [
StoreModule.forRoot(rootReducer, { metaReducers }),
...
]
