Can't get Webpack 2 HMR React to work

不问归期 提交于 2019-11-29 15:14:35

The imports are static and after an update has been identified in module.hot.accept you render the exact same component again, as the TodoApp still holds the old version of your module and HMR realises that and doesn't refresh or change anything in your app.

You want to use Dynamic import: import(). To make it work with babel you need to add babel-plugin-syntax-dynamic-import, otherwise it will report a syntax error as it didn't expect import to be used as a function. The react-hot-loader/babel is not needed if you use react-hot-loader/patch in your webpack config, so your plugins in your .babelrc become:

"plugins": [
  "syntax-dynamic-import"
]

In your render() function you can now import the TodoApp and render it.

const render = () => {
  import('./components/TodoApp').then(({ default: Component }) => {
    ReactDOM.render(
      <AppContainer>
        <Component />
      </AppContainer>,
      document.querySelector('#main')
    );
  });
};

render();

// Hot Module Replacement API
if (module.hot) {
  module.hot.accept('./components/TodoApp', render);
}

import() is a promise that will resolve with the module, and you want to use the default export.


Even though the above is true, the webpack documentation doesn't require you to use dynamic imports, because webpack handles ES modules out of the box, also described in react-hot-loader docs - Webpack 2, and because webpack is also handling the HMR, it will know what to do in that case. For this to work, you must not transform the modules to commonjs. You did this with ["es2015", {"modules": false}], but you also have the latest preset configured in your webpack config, which also transforms the modules. To avoid confusion, you should have all babel configurations in .babelrc instead of splitting some to the loader options.

Remove the presets in the babel-loader entirely from your webpack config and it will work as you already have the necessary presets in your .babelrc. babel-preset-latest is deprecated and if you want to use these features you should start using babel-preset-env which also replaces es2015. So your presets in .babelrc would be:

"presets": [
  ["env", {"modules": false}],
  "react"
],

Check this issue on GitHub or just use this in your index.js:

import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'

import App from './components/App'

const render = Component => { 
    ReactDOM.render(
        <AppContainer>
            <Component/>
        </AppContainer>,
        document.getElementById('react-root')
    )
}

render(App)

if(module.hot) {
    module.hot.accept();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!