I'm using redux-form and it provides a built-in reducer, called "formReducer" that need to be registered with the combined reducers to manage the form state with redux's store.
I'm also using redux-persist to persist the redux store.
The problem raised when I don't want to have my form automatically re-populate the data entered by the user on page reloading or page refreshing. In a normal reducer written by my own, I can simply add an switch case for action of type "REHYDRATE" (dispatched by redux-persit) to prevent the state slice from auto-rehydrating by just returning its initial state or an empty state. But redux-form's formReducer is built-in provided by redux-form, so I cannot change. So, is there any way to "customize" the redux-form reducer to add that switch case? Or, is there any way I can config redux-persist to not auto-rehydrate a specific state slice, or is there any way I can config redux-form to not being auto-populated by page reloading or page refreshing?
"persist/REHYDRATE":This phase is where the persisted data stored in browser replace the data in Redux store. Across all reducers, every local state is "rehydrated" and is replaced by the persisted store. Each reducer replaces their content by the persisted one.
According to the docs, persistReducer "returns an enhanced reducer". I guess this means that it wraps your reducer into a function that will persist the new state for you automatically.
When we refresh page in a web-app, the state always resets back to the initial values which in not a good thing when you try to build some large web-app like e-commerce. We can manually do the state persistent using the native JavaScript localStorage.
I have a "perfect" solution based on suggestion by @jpdelatorre from this thread How to handle redux-form/CHANGE in reducer
Basically it's to "extend" the formReducer provided by redux-form, then add switch case for the event "REHYDRATE":
import { reducer as reduxFormReducer } from 'redux-form'
import { REHYDRATE } from 'redux-persist/constants'
const formPlugin = {
my_redux_form_name: (state, action) => {
switch (action.type) {
case REHYDRATE:
return {}
default:
return state
}
}
}
const formReducer = reduxFormReducer.plugin(formPlugin)
export default formReducer
then have the extended reducer to register with the root reducer.
import formReducer from './form.reducer'
const rootReducer = combineReducers({
...other reducers,
form: formReducer
})
If you are using the latest (v5) redux-persist version, in the persistConfig option there's a whitelist key-option where you whitelist which reducers should be persisted/rehydrated. You should use that, e.g:
const persistConfig = {
key: 'root_key_in_localstorage',
storage,
whitelist: ['session'],
}
You can use a Middleware that will handle this specific action type and prevent it from being passed to the reducers.
const myMiddleWare = store => next => action => {
if(action.type != 'REHYDRATE'){
next(action); // pass the action forward to the reducers
} else{
// do your logic here, you can use store.dispatch to dispatch other actions
// when your not invoking next(action) this action won't pass through to all the reducers
}
}
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