0

Probably it's one of thousands of similar questions, but I still didn't see any answer about how to make HMR REALLY work.

I did all that manipulations, described in docs and in every answer you can find all over internet:

  • enable "hot" option of webpack-dev-server
  • add webpack-dev-server/client?{host:port} and webpack/hot/only-dev-server entry points
  • add new webpack.HotModuleReplacementPlugin() to plugins (and NamedModulesPlugin too)
  • every step from docs of react-hot-loader

And now what I have.

Let say my app looks like this:

<ReactRouter>
  <App>
    <AppRouter />
  </App>
</ReactRouter>

where AppRouter is like

<Switch>
  <Route path="..." component={Page} />
  ...
</Switch>

and Page is just <div>some text<div>.

Accordingly to docs, in App module I do:

import { hot } from "react-hot-loader"
export default hot(module)(App)

and then trying to modify text in Page component to "new text".

In console I see that HMR is enabled indeed:

[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR]  - ./AppRouter.js
[HMR]  - ./App.js
[HMR] App is up to date.

and text on screen really updates to "new text". So far so good.

Then I update text once again, to "new text 2", and see this:

Ignored an update to unaccepted module ./Page.js -> ./AppRouter.js -> ./App.js
[HMR] The following modules couldn't be hot updated: (They would need a full reload!)
[HMR]  - ./Page.js

There is nothing about this in react-hot-loader docs.

But ok, maybe that doc is slightly incorrect. After all, webpack own docs explicitly shows that we should do module.hot.accept(...) in our code.

So in App.js I do:

if (module.hot) {
  module.hot.accept("./AppRouter", () => {
    console.log("It works!")
  })
}

then refreshing the page, and trying to modify Page component again.

Now console says following:

[WDS] App hot update...
[HMR] Checking for updates on the server...
App.js:20 It works!
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR]  - ./AppRouter.js
[HMR]  - ./App.js
[HMR] App is up to date.

But text in browser is not updated. I.e., HMR is enabled but does nothing.

Succeeding updates says:

[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR] App is up to date.

so at least we fixed previous error with unaccepted changes – but still nothing changes in browser.

I tried to do module.hot.accept(...) both when App is decorated with hot(module) and when it's not – result is the same.

And... what next? I did everything I can find in official docs, and nothing of it works. What am I doing wrong?

(and please, please don't ask "provide your full webpack config before we talk". It's all default, accordingly to example from webpack docs. Don't waste our time on this)

jeron-diovis
  • 788
  • 1
  • 8
  • 19

1 Answers1

0

When you accept a file, you have to do the things yourself (the exchanging of the component for example). So do sth. like this:

if (module.hot) {
  module.hot.accept("./AppRouter", () => {
    const NewAppRouter = require('./AppRouter').default;
    const newApp = (
       <ReactRouter>
          <App>
             <NewAppRouter />
          </App>
       </ReactRouter>
    );
    ReactDom.render(newApp, container);
  });
}

Here I get notified when the file changed. Then I require the changed file and rerender my app with the new file. This works best, when you use a statemanagement lib like redux or mobx, because your application's state won't change when you rerender your app.

Daniel
  • 1,933
  • 12
  • 17