I am using Redux for state management.
How do I reset the store to its initial state?
For example, let’s say I have two user accounts (u1
and u2
).
Imagine the following sequence of events:
User
u1
logs into the app and does something, so we cache some data in the store.User
u1
logs out.User
u2
logs into the app without refreshing the browser.
At this point, the cached data will be associated with u1
, and I would like to clean it up.
How can I reset the Redux store to its initial state when the first user logs out?
In addition to Dan Abramov's answer, shouldn't we explicitly set action as action = {type: '@@INIT'} alongside state = undefined. With above action type, every reducer returns the initial state.
Another option is to:
'@@redux/INIT'
is the action type that redux dispatches automatically when youcreateStore
, so assuming your reducers all have a default already, this would get caught by those and start your state off fresh. It might be considered a private implementation detail of redux, though, so buyer beware...UPDATE NGRX4
If you are migrating to NGRX 4, you may have noticed from the migration guide that the rootreducer method for combining your reducers has been replaced with ActionReducerMap method. At first, this new way of doing things might make resetting state a challenge. It is actually straight-forward, yet the way of doing this has changed.
This solution is inspired by the meta-reducers API section of the NGRX4 Github docs.
First, lets say your are combining your reducers like this using NGRX's new ActionReducerMap option:
Now, lets say you want to reset state from within app.module `
`
And that is basically one way to achieve the same affect with NGRX 4.
The following solution worked for me.
I added resetting state function to meta reducers.The key was to use
to set all reducers to initial state. Returning
undefined
instead was causing errors due to the fact that the structure of the store has been destroyed./reducers/index.ts
app.module.ts
From a security perspective, the safest thing to do when logging a user out is to reset all persistent state (e.x. cookies,
localStorage
,IndexedDB
,Web SQL
, etc) and do a hard refresh of the page usingwindow.location.reload()
. It's possible a sloppy developer accidentally or intentionally stored some sensitive data onwindow
, in the DOM, etc. Blowing away all persistent state and refreshing the browser is the only way to guarantee no information from the previous user is leaked to the next user.(Of course, as a user on a shared computer you should use "private browsing" mode, close the browser window yourself, use the "clear browsing data" function, etc, but as a developer we can't expect everyone to always be that diligent)
If you are using redux-actions, here's a quick workaround using a HOF(Higher Order Function) for
handleActions
.And then use
handleActionsEx
instead of originalhandleActions
to handle reducers.Dan's answer gives a great idea about this problem, but it didn't work out well for me, because I'm using
redux-persist
.When used with
redux-persist
, simply passingundefined
state didn't trigger persisting behavior, so I knew I had to manually remove item from storage (React Native in my case, thusAsyncStorage
).or
didn't work for me either - they just yelled at me. (e.g., complaining like "Unexpected key _persist ...")
Then I suddenly pondered all I want is just make every individual reducer return their own initial state when
RESET
action type is encountered. That way, persisting is handled naturally. Obviously without above utility function (handleActionsEx
), my code won't look DRY (although it's just a one liner, i.e.RESET: () => initialState
), but I couldn't stand it 'cuz I love metaprogramming.