Reset redux store on specific action
I try to reset the redux store (logout behavior) but I can't find a simple solution that allows me to do it globally when using redux-dynamic-modules. Before using redux-dynamic-modules, I used to do what Dan was proposing here with the combineReducer function. https://stackoverflow.com/a/35641992/6765022 Now I understand that we have to send a map of reducers to the createStore function that will take care of everything. Therefore, I cannot intercept the creation of the reducers to listen to a logout action. Anyone have any idea how to implement this behavior?
What do you mean by reset redux store? If you want to reset state(s) to some "default" value you can catch "logout" action in all the reducers that control the states you want to reset. If you want to unload some modules from redux store you should unmount (in other words stop render) components that loaded modules via DynamicModuleLoader
I mean reset the store to its default value. Obviously it is possible to listen in all reducers, but I was looking for a solution to only have to add a "custom" case when creating the store as it is possible to do easily without this library. Normally I could do something like that :
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
state = undefined
}
return appReducer(state, action)
}
but not anymore since I have to provide a map of reducers that have not yet been "combined" together with combineReducers.
export const getRootModule: ISagaModule<ApplicationState> = {
id: 'root',
reducerMap: myReducerMap as any, <-- Here, I have to provide a list of reducers
sagas: [rootSaga],
};
And myReducerMap looks like this
export const myReducerMap = {
router: connectRouter(history),
authentication: authenticationReducer,
userPictures: userPictureReducer,
pictureUploader: pictureUploaderReducer,
// other reducers...
};
```
you can describe your module like this:
function getModule1() {
return {
id: "module1",
reducerMap: {
module1: module1Reducer // only one key in map
}
}
}
and then you could use combineReducers or whatever to create module1Reducer. Inside module1Reducer you could reset state as you did before. If you want to reset state of 2 separate modules you should do it in 2 separate reducers because they control separate state.
@CharlesMcD Have you figured out how to do this? @abdurahmanus I think what you said makes sense. But currently I'm converting a monolithic redux store to dynamic modules step by step. I need this one call that reset all my registered root level keys to default value without adding a new key. Is this possible? What's the correct way to do it?
I never really found the solution I was looking for to my problem. The walkaround is used was to listen in each reducer for the "logout" action. It was a small project so it's not that bad, but I understand that it can be a pain in the ass in a big project. I didn't really understood @abdurahmanus last solution because I couldn't use combineReducers function to generate the "module1Reducer" from his example. I absolutely had to provide a list of reducer to the "reducerMap" key.
@CharlesMcD What he meant was to create a new key on top of the gaint object, like module1: module1Reducer here the module1Reducer is your rootReducer from:
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
state = undefined
}
return appReducer(state, action)
}
In this way you can reset all in your original myReducerMap but you'll make it one level deeper. combineReducer works like https://github.com/microsoft/redux-dynamic-modules/blob/master/packages/todo-example/src/modules/shoppinglist/reducers/index.js
@navneet-g @abettadapur Idea on how to reset whole state besides each module implement its own logout? Use case is when user logout, we want to reset all modules to initialState... This is the only blocker right now...
One idea is that you could recreate the store entirely, through some side-effect, but that doesn't seem like a great solution.
Honestly, I think this is just a limitation of our library, because we do not support nested modules. @navneet-g Do you think there is a way we could support this usecase?
How about adding a reducer to the moduleStoreSettings that can act on the overall store state? This would also help with #58 and other cases where enhancers depend on reducers being in place.
Sorry I missed it, I will take a look soon.
You can send a custom advancedCombineReducers to ModuleStore, and wrap the reducer with reset action, something similar to idea described in https://alligator.io/redux/reset-state-redux/
This is really easy @CharlesMcD @ryanf5. Like @navneet-g suggested:
const store = createDynamicStore({
// initialState: { },
// extensions,
advancedCombineReducers: combineReducersWithReset
},
/* core modules */
);
and
import { combineReducers } from 'redux';
const combineReducersWithReset = (...args) => {
const rootReducer = combineReducers(...args);
return (state, action) => {
if (action.type === LOGOUT)
return rootReducer({}, action);
return rootReducer(state, action);
}
};