Component not reloaded with react hot loader

1.7k Views Asked by At

https://github.com/James2516/hot-reload

I'm trying to add hot loader to an existing webpack project.

It detected file changes but did not reload the component.

To reproduce:

  1. yarn && yarn start
  2. change src/App.js content
1

There are 1 best solutions below

2
On BEST ANSWER

The examples are taken from https://gaearon.github.io/react-hot-loader/getstarted/#step-2-of-3-using-hmr-to-replace-the-root-component, though it seems as though you already followed this guide.

The first problem is that [HMR] Waiting for update signal from WDS... is printed to the console twice, and any attempted recompiles also occur twice. This is caused by your entry in ./config/webpack/Dev.js being:

entry: [
  'webpack-dev-server/client?http://localhost:4545/',
  'webpack/hot/only-dev-server',
  'react-hot-loader/patch',
  './client.js',
]

The first few steps of the guide have the entry point as:

[
  'webpack-dev-server/client?http://0.0.0.0:3000', // WebpackDevServer host and port
  'webpack/hot/only-dev-server', // 'only' prevents reload on syntax errors
  './scripts/index' // Your app's entry point
]

Step 3a under Step 3 (of 3): Adding React Hot Loader to preserve component state instructs you to modify the entry of webpack.config.js to look like:

[
  'react-hot-loader/patch', // RHL patch
  './scripts/index' // Your app's entry point
]

react-hot-loader handles what these two entries were previously doing, so they can be replaced with 'react-hot-loader/patch'.

So your new entry point should be:

[
  'react-hot-loader/patch',
  './client.js'
]

Next, Step 3b in the same section has a code snippet that looks like:

if (module.hot) {
  module.hot.accept('./containers/rootContainer.js', () => {
    const NextRootContainer = require('./containers/rootContainer').default;
    render(NextRootContainer);
  });
}

Changing your module.hot block to:

if (module.hot) {
  module.hot.accept('./App', () => {
    const newApp = require('./App').default;
    render(newApp);
  }
}

Correctly reloads the component, so it doesn't make sense that following Step 3c breaks HMR.

c. Webpack 2 has built-in support for ES2015 modules, and you won’t need to re-require your app root in module.hot.accept. The example above becomes:

if (module.hot) {
  module.hot.accept('./containers/rootContainer', () => { 
   render(RootContainer) });
}

Note: To make this work, you’ll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be

"presets": [["es2015", { "modules": false }]]

Which you did correctly in .babelrc. The only problem is that in ./config/webpack/Base.js you have:

loader: 'babel-loader',
query: {
  presets: ['es2015', 'react', 'stage-2']
}

This causes babel-loader to use these presets instead of the ones defined in .babelrc. Removing query in this rule and changing presets in .babelrc to:

"presets": [["es2015", { "modules": false }], "react", "stage-2"

Correctly enables HMR with your module.hot block as:

if (module.hot) {
  module.hot.accept('./App', () => { render(App); });
}