I am trying to deal with the problem, addressed, in general in an earlier thread - How to reset the state of a Redux store? - the need to reinitialize/invalidate the entire redux store on user logout.
In my case, however, something is still missing. I am using Redux with ConnectedRouter and I tried to do the following.
Define the rootReducer as:
export default history =>
combineReducers({
router: connectRouter(history),
user,
manager,
vendor
// rest of your reducers
});
Then I do configureStore
, importing the above as createRootReducer
:
const configureStore = (initialState = {}, history) => {
let composeEnhancers = compose;
const composeWithDevToolsExtension =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
const enhancers = [];
const middleware = [sagaMiddleware, thunk, routerMiddleware(history)];
if (typeof composeWithDevToolsExtension === 'function') {
composeEnhancers = composeWithDevToolsExtension;
}
const store = createStore(
createRootReducer(history), // root reducer with router state
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
store.runSaga = sagaMiddleware.run;
store.subscribe(() => {
const state = store.getState();
const { session } = state['user'];
if (!session) {
console.log('no valid session');
initialState = undefined;
} else {
const { token } = session;
const decodedToken = jwt_decode(token);
const { exp } = decodedToken;
const now = new Date();
if (exp > now.getTime()) {
console.warn('token expired');
initialState = undefined;
} else {
console.log('token valid');
}
}
});
return store;
};
export default configureStore({}, history);
The idea is that initialState = undefined;
should reset my state. It is not working for me though.
Where would be the correct place to do this, given that I am using the ConnectedRouter
and passing the history
object to it?
Redux-persist keeps a copy of your state in a storage engine, and the state copy will be loaded from there on refresh. First, you need to import the appropriate storage engine and then, to parse the state before setting it to undefined and clean each storage state key.
All data in redux store will be cleared to initial state when client refresh our application on the browser or close the browser's tab. So if our application have about user permission, role or something that for protected data.
To reset a component to its initial state:Store the initial state in a variable. When an event occurs, call the setState() function, passing it the initial state.
Redux restricts updating the state to this method only. This strict way of updating the state ensures that the state can not be changed directly either by view or any network callback. The only way to update a state is by defining the action and then dispatching it. Remember that actions are plain JavaScript objects.
The trick to reuse the logic for resetting the app in a single place is to create a root reducer over your app root reducer. That is a reducer on top of your reducers where you check for that condition and apply it if necessary. Usually, you would use the combineReducers function to create a single root reducer for your redux store:
Steps to reset the state of a redux store. 1. Implement redux store in ReactJS. In order to show you the example, you have to implement redux store in ReactJS. If you don’t know how to ... 2. Update store to reset state. 3. Update component to reset the store. 4. Output.
When you do a new redux state, with empty content, you basically still have the previous states in memory, and you could theoretically access the data from them. Refreshing the browser IS your safest bet! With Redux if have applied the following solution, which assumes I have set an initialState in all my reducers (e.g. { user: { name, email }} ).
This way whenever you call RESET action, you reducer will update the store with default state. const logoutHandler = () => { store.dispatch (RESET_ACTION) // Also the custom logic like for the rest of the logout handler } Every time a userlogs in, without a browser refresh. Store will always be at default.
I wanted to point out to a couple of things that are pretty important before I give you a solution:
When using redux you should never attempt to alter the state of your store directly. The state should always change through the reducer as a reaction to an action. Therefore, reassigning the parameter initialState
inside that subscribe
callback is incorrect and pointless.
I don't think that you want to "reset" the state of the router
property, correct?
One way to solve this is to use a reducer enhancer, something like this:
const resetEnhancer = rootReducer => (state, action) => {
if (action.type !== 'RESET') return rootReducer(state, action);
const newState = rootReducer(undefined, {});
newState.router = state.router;
return newState;
};
And then when you create your store do this:
const store = createStore(
resetEnhancer(createRootReducer(history)),
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
);
And in that subscribe
callback do this:
if (!session) {
store.dispatch({type: 'RESET'});
}
One last extra-tip: since you are using redux-saga
I strongly suggest that you move what you are doing inside that subscribe
callback into a saga.
You can make an action for clearing the store and use it in your rootReducer
as like this:
const appReducer = combineReducers({
... // your reducers
});
const rootReducer = (state, action) => {
if (action.type === 'CLEAR_STORE') return appReducer(undefined, action);
return appReducer(state, action);
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const configureStore = (initialState, history) =>
createStore(
connectRouter(history)(rootReducer),
initialState,
composeEnhancers(applyMiddleware(routerMiddleware(history), thunkMiddleware))
);
You'll have appReducer
with all your reducers but also rootReducer
which will be the function that will determinate returning a corresponding value or an undefined one.
TIP: You can use your Logout action rather than using a new action just for clearing the store
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