Keep redux store in HMR.
Lost redux store in HMR.
Intergrate with https://github.com/gaearon/react-hot-loader
| Software | Version(s)
| ---------------- | ----------
| Parcel | 1.2.0
| Node | 8.9.3
|Yarn | 1.3.2
| Operating System | macOS 10.12
workaround:
const store = (() => {
if ((process.env.NODE_ENV === 'development)' && window.store) {
return window.store;
}
const store = createStore(/*...*/);
if (process.env.NODE_ENV === 'development') {
window.store = store;
}
return store;
})()
This works better for me:
function configureStore() {
if (window.store == null) {
window.store = createStore(rootReducer);
return window.store;
}
if (process.env.NODE_ENV === "development") {
window.store.replaceReducer(rootReducer);
}
return window.store;
}
const store = configureStore();
If you try to add react-hot-loader you get a funny error. The hot loading works* but you get a console error in: cached.hot._acceptCallback();
If i change the code to cached.hot.acceptCallback();
no console error is logged and everything works* perfectly as it did before.
(*) The hot loading works.
I think we may need to clarify this to the community I get a feeling that hot loading works differently in parcel and we cannot use webpack's api: if(module.hot)
. I don't say it is a bug, we might just claridy we execute everything again and if you want to run something once you have to store it on windows and check if that is null (a sort of lazy load on the windows object).
I don't have an issue with that, I think is even better than having an api. Or calling a new library like react hot loader to keep state. But I think we should be explicit about this hmr flavour and that parcel doesn't needs React hot loader.
If your root reducer is composed of an object of reducers in a file store/reducers
:
import reducers from '../../store/reducers'
[...]
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept(() => {
const nextRootReducer = combineReducers({
...require('../../store/reducers').default
})
store.replaceReducer(nextRootReducer)
})
}
Parcel doesn't allow to write down the dependency as first argument of module.hot.accept
. Now, whenever one of the dependencies of this file, like on of the reducers, changes, your store will be persisted, whilst the reducers will be replaced.
adding this just for search ability when googling, thats what my dev tools throw
store
on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.
HMR seems to work even if I don't use module.hot.accept
anywhere in my codebase (I wasn't expecting this behaviour?).
As such, I can't seem to avoid it replacing the store since the root file gets reloaded, which is a shame.
I think a better solution is adding a dispose callback (code not tried):
// create store with saved initialState (note: as with SSR)
const store = createStore(reducers, window.initialState);
if (module.hot) {
// save current state before module being reloaded
module.hot.dispose(() => window.initialState = store.getState());
}
Most helpful comment
adding this just for search ability when googling, thats what my dev tools throw
store
on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.