React-hot-loader: content doesn't reload

Created on 9 Mar 2017  路  14Comments  路  Source: gaearon/react-hot-loader

If you are reporting a bug or having an issue setting up React Hot Loader, please fill in below. For feature requests, feel free to remove this template entirely.

Description

HMR is working but content is not reloading
What you are reporting:
bug

Expected behavior

content gets reloaded
What you think should happen:

Actual behavior

What actually happens:

Environment

windows 8.1 npm 4.1.1 "webpack": "^2.2.0", "webpack-dev-server": "^2.4.1", "react-hot-loader": "^3.0.0-beta.6", "react-redux": "^4.4.6",
React Hot Loader version:
"react-hot-loader": "^3.0.0-beta.6"
Run these commands in the project folder and fill in their results:

  1. node -v: 6.9.4
  2. npm -v: 4.1.1

Then, specify:

  1. Operating system: windows 8.1
  2. Browser and version: chrome latest

Reproducible Demo

Please take the time to create a new project that reproduces the issue.
in the index.jsx

import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Router, browserHistory } from 'react-router';
import { Provider } from 'react-redux';
import Routes from './Routes';
import WidgetsApp from './App';
import WidgetsStore from './Store';
import './index.html';

const store = WidgetsStore.configureStore();
const rootElement = document.getElementById('root');
const appRender = (App) => {
    render(<AppContainer>
               <Provider store={ store }>
                   <App/>
               </Provider>
           </AppContainer>, rootElement);
};
appRender(WidgetsApp);

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

in .babelrc

{
  "presets": [
    ["es2015", {"loose" : true, "modules": false}],
    //Webpack understands the native import syntax, and uses it for tree shaking

    "stage-0",
    //Specifies what level of language features to activate.
    //State 2 is "draft", 4 is finished, 0 is strawman.
    //See https://tc39.github.io/process-document/

    "react"
    //Transpile React components to JS
  ],
  "env": {
    "test": {
      "plugins": [ "istanbul" ]
    }
  },
  "plugins": ['transform-runtime', 'transform-decorators-legacy', 'transform-class-properties', 'react-hot-loader/babel']
}

in webpack.config.js

entry: {
        app: [
            'babel-polyfill',
            'react-hot-loader/patch',
            './src/index.jsx'
        ],
        vendor: [
            './src/Vendor.jsx'
        ]

You can copy your project that experiences the problem and start removing things until you鈥檙e left with the minimal reproducible demo. This helps contributors, and you might get to the root of your problem during that process.

I think what cause the problem is the Provider if I don't use it it works fine

Push to GitHub and paste the link here.

bug

Most helpful comment

I got this working now. There were two things I needed to change.
First I was wrapping the App component in with redux's \

and then I tried what someone suggested here https://github.com/webpack/webpack-dev-server/issues/100#issuecomment-271146394

..and re-imported the App component inside if (module.hot) {...}

Like this:

// Hot Module Replacement API
if (module.hot) {
  const NextApp = require('components/App').default;
  module.hot.accept('components/App', () => { render(NextApp) })
}

All 14 comments

I'm experiencing the same problem.

I've got a project where components that has state injected from the store will not reload and the same goes for all child components to those components.

However components without store connection or ancestors reloads just fine.

Versions:

I got this working now. There were two things I needed to change.
First I was wrapping the App component in with redux's \

and then I tried what someone suggested here https://github.com/webpack/webpack-dev-server/issues/100#issuecomment-271146394

..and re-imported the App component inside if (module.hot) {...}

Like this:

// Hot Module Replacement API
if (module.hot) {
  const NextApp = require('components/App').default;
  module.hot.accept('components/App', () => { render(NextApp) })
}

@sylhero could you try to put <Provider> into the <App>? Also, full repo would really help here.

@wkwiatek thanks for replying me. I tried your suggestion but still not working. I can not provide a repo but it's easy to reproduce.

@HeyHugo thanks for the solution!

@HeyHugo Thank for the solution! It works well!

I did not need to move the Provider into the app but re-importing directly inside the accept seemed to fix things. @HeyHugo it looks like you may have a typo doing the require before module.hot.accept? The issue you link to does the require inside, ala

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

I fought with this a long while, so for anyone else here's the basics of my setup for react / redux / react-router v4.

// index.js (the entrypoint for webpack)

require('../css/index.scss');
require.context('../images', true, /^\.\//);

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

import { Provider } from 'react-redux';
import { compose, createStore } from 'redux';
import persistState from 'redux-localstorage';
import rootReducer from './state';


const enhancer = compose(
  persistState('settings'),
);

const initialState = undefined; // eslint-disable-line no-undefined

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

import App from './App';

const rootEl = document.getElementById('Root');
// Render the main component into the dom
const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Provider store={store}>
        <Component />
      </Provider>
    </AppContainer>,
    rootEl
  );
};

render(App);

if (module.hot) {
  module.hot.accept('./App', () => {
    const App = require('./App').default;
    render(App);
  });
}
// App.jsx
import React from 'react';
import { BrowserRouter } from 'react-router-dom';

import NavigationRoute from 'routes/NavigationRoute';

// Render the main component into the dom
export default class App extends React.Component { //eslint-disable-line react/require-optimization
  render() {
    return (
      <BrowserRouter>
        <NavigationRoute />
      </BrowserRouter>
    );
  }
}
// NavigationRoute.jsx (simplified)

import React from 'react';
import { Redirect, Route, Switch } from 'react-router';

import Header from 'components/Header';

import EmergencyRoute from 'routes/EmergencyRoute';
import MapRoute from 'routes/MapRoute';
import MoreRoute from 'routes/MoreRoute';

class NavigationRoute extends React.Component {
  shouldComponentUpdate() {
    return true;
  }

  render() {
    return (
      <div className='NavigationRoute'>
        <Header />
        <div className='NavigationRoute-content'>
          <Switch>
            <Route path='/emergency' component={EmergencyRoute} />
            <Route path='/more' component={MoreRoute} />
            <Route path='/map' component={MapRoute} />
            <Redirect from='*' to='/map' />
          </Switch>
        </div>
      </div>
    );
  }
}

NavigationRoute.propTypes = {};

export default NavigationRoute;

I'm getting this too (see my mistakenly reported ticket here: https://github.com/webpack/webpack/issues/4703)

Is this if(module.hot) thing _the_ solution, or just a hack? Given that none of the webpack docs indicate this is necessary, they should at least be updated if so.

@HeyHugo Hi. Thanks for the solution. If you reimport that module, in if (module.hot), it works, but it seems that the page is doing a force reloading, and all the redux state gets lost. So you sure, in your case, it's an HMR rather than a page reload? Thanks :)

@HeyHugo It is works for me , thanks

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

BTW , when i use lazy loading , this is still not work for me

For my case, it was caused by the .babelrc configuration. You need to config the babel to disable module transformation. I do the set as below:
{ "presets": [ ["env", { "modules": false }] ] }
Then the reload works well.

Keep in mind - when you don't use harmony modules, ie not transpiled import/export, you have to re-require updated module by yourself.
When you will enable them (by disabling babel modules) as @ehe888 said - everything will work out of the box.

The two modes (harmony and cjs) are now supported with new hot setup. React Hot Loader v4 is ready to be tested! Give it a try!

@ehe888 your comment solved my issue of my Home component not updating in the DOM/reloading the updated file into sources. The HMR console logging says "successful" but it never updated since source file was not being refreshed.

Can you explain this more? i am new to Webpack & babel configs. This is my updated .babelrc file:

{
  "presets": [["env", { "modules": false }], "react", "stage-1"],
  "plugins": ["react-hot-loader/babel"]
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

reintroducing picture reintroducing  路  4Comments

calvinchankf picture calvinchankf  路  3Comments

theKashey picture theKashey  路  3Comments

rockchalkwushock picture rockchalkwushock  路  3Comments

JamesIves picture JamesIves  路  4Comments