I am using Angular 2 with ngrx/store. I want to reset the whole store states when user dispatch USER_LOGOUT
.
I read the Dan Abramov's answer of How to reset the state of a Redux store?, but I didn't figure out how to write rootReducer
correctly and where to put it when using ngrx/store.
Or is there any other way to handle this in ngrx/store?
bootstrap(App, [
provideStore(
compose(
storeFreeze,
storeLogger(),
combineReducers
)({
router: routerReducer,
foo: fooReducer,
bar: barReducer
})
)
]);
In ngrx/store 4.x, this can be accomplished with Meta-reducers. As I understand it, all actions are passing through the metareducers before being handed over to the feature reducers. This gives us the opportunity to change/reset the state first.
Here's an example.
This is my metareducer function: in case the action is of type LOGOUT, the state is re-initialized.
function logout(reducer) {
return function (state, action) {
return reducer(action.type === LOGOUT ? undefined : state, action);
}
}
Below you see how the metareducer is configured along with the feature reducers. Should there be more than 1 metareducer, then they are evaluated from right to left
StoreModule.forRoot({rooms: roomReducer, user: userReducer}, {metaReducers: [logout]})
Finally, I also have an @effect where I navigate to the login page
@Effect({dispatch: false}) logout: Observable<Action> =
this.actions$.ofType(LOGOUT)
.do(() => {
// ... some more stuff here ...
this.router.navigate(['/login page'])
});
This answer is specific to ngrx version 2. The question has another, more recent answer that explains how the same can be done with ngrx version 4.
compose
builds the ngrx root reducer.
The arguments passed to compose
are functions that return a reducer - composed from the reducer they themselves are passed as an argument. You can compose the resetting of your store like this:
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
})
)
]);
Note that this will reset all of the store's state - including the router
. If that's not what you want, you could tweak the example.
With introduction of NgModule
the bootstrapping has changed, but you still pass the composed reducer to provideStore
:
import { compose } from "@ngrx/core/compose";
import { StoreModule } from "@ngrx/store";
@NgModule({
...
imports: [
...
StoreModule.provideStore(compose(...))
],
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With