React-hot-loader: Issue with Redux store after reload using NEXT

Created on 10 Jan 2018  路  14Comments  路  Source: gaearon/react-hot-loader

Description

I've upgraded my project to use 4.0.0-beta.13 - the hot reloading works (in the sense that the app builds, reloads on changes etc) but the redux store doesnt retain state after reload, I am using react-router 4.2.0

Expected behavior

Redux Store should remain populated as before reload

Actual behavior

Redux store is only populated to single nested level , so the top level objects that are on the same hierarchical level as router exist, as do the objects below them but nothing below that (except for router)

Simplified Example of store before reload

  • router

    • location

    • path

  • search

    • keys

    • keys[0]

    • keys[1]

    • keys[2]

Simplified Example after reload

  • router

    • location

    • path

  • search

    • keys

Environment

React Hot Loader version:

Run these commands in the project folder and fill in their results:

  1. node -v: 9.3.0
  2. npm -v: 5.6.0

Then, specify:

  1. Operating system: MacOS High sierra 10.13.2
  2. Browser and version: Electron 1.7.10
bug

Most helpful comment

@anthonator - don't use hot in index.js or Root. Use hot in App.js only, don't re-create store, as you are doing it now.

All 14 comments

Redux store might be ok even without any RHL. Look like you have problem with HRM setup.
The simple trick to check - add console.log just next to the state creating. It should __not__ be called on a component update, only on full page reload.

So the store is getting recreated as per your suggestion for checking this. The store is created in index.js which is the entry point for the webpack-dev-server - is this correct? I think I'm missing something obvious in how this should be configured. My App component is marked for hot-reload export default hot(module)(App)- the App component is the container wraps the routes

<App>
    <Switch>
      <Route path="/home" component={HomePage} />
        ...
    </Switch>
  </App>

To confirm I am getting a full page reload when any file is changed

Can not help without full sources.

I think I may be seeing something similar.

This sounds similar to what I'm seeing as well.

Here's what I've got:

createStore.js

import { applyMiddleware, createStore } from 'redux';

import withDevTools from './withDevTools';
import middleware from '../../redux/middleware';
import rootReducer from '../../redux';

export default function (state = {}) {
  let enhancer = applyMiddleware(...middleware);

  enhancer = withDevTools(enhancer);

  const store = createStore(rootReducer, state, enhancer);

  if (module.hot) {
    module.hot.accept('../../redux/index', () => {
      const nextReducer = require('../../redux/index').default; // eslint-disable-line global-require

      store.replaceReducer(nextReducer);
    });
  }

  return store;
}

index.jsx (entry point)

import React from 'react';
import { render } from 'react-dom';

import Root from './Root';

render(<Root />, document.getElementById('root'));

Root.jsx

import React from 'react';
import { hot } from 'react-hot-loader';

import createStore from './lib/redux/createStore';

// components

import { Provider } from 'react-redux';

import App from './components/App';

const store = createStore();

function Root() {
  return (
    <Provider store={ store }>
      <App />
    </Provider>
  );
}

export default hot(module)(Root);

App.jsx

import React from 'react';

export default function () {
  return (
    <div>Hello, world!!!!!!!</div>
  );
}

As you can see, it's very simple. Whenever I update App.jsx my store resets and I see the following warning:

warning.js:10 <Provider> does not support changing `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.

Using react-hot-loader-4.0.0-beta.21

@anthonator - don't use hot in index.js or Root. Use hot in App.js only, don't re-create store, as you are doing it now.

@theKashey thanks! 鉂わ笍

@theKashey am I required to export every module that I want hot-reloaded this way?

export default hot(module)(App);

I never had to do this before, everything worked fine using the usual <AppContainer> method. Has something changed in the beta?

You even could still use AppContainer + webpack HRM.
V4 just provide a helper function for easy setup.
Usually, it is enough to wrap top level component with hot, and do the same with async chunks. Ie you can just read this recommendation as "wrap top-level component of a chunk or entry point".

Thanks for the quick response, I appreciate it. That makes sense! I've got it sorted now :)

@theKashey I'm experiencing the same problem with @anthonator, Can you please elaborate more when you said "don't re-create store" and what's the right way doing it?

@panuta - you just cant hot-reload the "entry" of your application - the file with createStore, or the file with react-dom/render, or the file merging all this stuff together.
__Reac__-hot-loader gonna to reload React components, and files used by them, not side effects.

In @anthonator example he injects store in Root.jsx - the side effect one should avoid. Just move store creation one component up (index.jsx), or (in this example) mark as __hot__ only App.jsx.

This issue seems to be fixed, React Hot Loader v4 is not out! Update!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

niba picture niba  路  4Comments

theKashey picture theKashey  路  4Comments

esturcke picture esturcke  路  3Comments

mtscout6 picture mtscout6  路  3Comments

reintroducing picture reintroducing  路  4Comments