I have implemented the Store for my App. After logout I want to reset store. But there is a problem.
Let's assume I have the following State:
subjects: {
subjectsLoaded: true
}
In component I'm subscribe to the store like that:
this.store.pipe(
select(areSubjectsLoaded),
tap((subjectsLoaded) => {
if (!subjectsLoaded) {
this.store.dispatch(loadSubjects());
console.log('Dispatching Subjects because they are not Loaded');
}
}),
filter(subjectsLoaded => subjectsLoaded),
takeUntil(this.unsubscribe$)
).subscribe();
After logout and reseting the store, it will looks like:
subjects: {
subjectsLoaded: false
}
Since I am subscribed to changes in the component, an action dispatch will be made. But I don't know how to prevent this.
I'm also using takeUntil
in order not to receive data after the destroy of the component
There is a small demo:
For clear the store I'm using metaReducers:
export const metaReducers: MetaReducer<AppState>[] = [clearState];
export function clearState(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
return (state: AppState, action: Action): AppState => {
if (action.type === '[Toolbar] User Logout') {
console.log('Clear state: ',state);
state = undefined;
}
return reducer(state, action);
};
}
I think you'll have to use something else than undefined
, because, as you've seen, you can no longer distinguish 'state has not been initialized' and 'state must reset'.
You could use a symbol
to differentiate these states.
export const RESET_STATE = Symbol('reset state');
// your meta-reducer
state = RESET_STATE;
return state;
Now you could recognize them this way:
this.store.pipe(
filter(state => state !== RESET_STATE),
select(areSubjectsLoaded),
/* ... */
)
If you don't want to repeat yourself, you could create a selector out of that logic and use it in your other selectors as well.