3

HMR isn't enabled for apps init'ed with create-react-app. There is a blog post about how one can enable it here: http://chrisshepherd.me/posts/adding-hot-module-reloading-to-create-react-app

ReactDOM.render(
  <App />,
  rootEl
);

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

I am trying to do something similar, though I have added redux and react-router-redux to the mix:

App.js

import React from 'react'
import { Provider } from 'react-redux'
import store from './store/store'
import routes from './routes'

const App = (
  <Provider store={store}>
    { routes }
  </Provider>
);

export default App;

routes.js

import React from 'react';
import { browserHistory, Router, Route } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import store from '../store/store';
import { AnonymousLayout } from '../layouts';
import { LoginForm } from './Login';

const history = syncHistoryWithStore(browserHistory, store);

export default (
  <Router history={history}>
    <Route path="/" component={AnonymousLayout}>
      <Route path="/login" component={LoginForm} />
    </Route>
  </Router>
);

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './client/App';

const rootEl = document.getElementById('root');

ReactDOM.render(
  App,
  rootEl
);

if (module.hot) {
  module.hot.accept('./client/App', () => {
    const NextApp = './client/App';
    ReactDOM.render(
        <NextApp />,
        rootEl
      );
  });
}

However, I just get this error:

Warning: [react-router] You cannot change <Router routes>; it will be ignored

Is there some way to hack HMR into this project?

Mister Epic
  • 16,295
  • 13
  • 76
  • 147

4 Answers4

3

Dan Abramov posted a solution that works for my situation:

index.js

// regular imports
ReactDOM.render(<App /> , document.getElementById('root'))

if (module.hot) {
  module.hot.accept('./App', () => {
    ReactDOM.render(<App />, document.getElementById('root'))
  })
}

store.js

import { createStore } from 'redux'

import rootReducer from './reducers'

const configureStore = () => {
  const store = createStore(rootReducer)

  if (process.env.NODE_ENV !== "production") {
    if (module.hot) {
      module.hot.accept('./reducers', () => {
        store.replaceReducer(rootReducer)
      })
    }
  }

  return store
}

export default configureStore
Mister Epic
  • 16,295
  • 13
  • 76
  • 147
  • Could you be so kind to share a small repo which has all the code (eg. also the store.js / index.js / app.js)? I can't seem to get it to work :( – NealVDV Jul 27 '17 at 11:06
  • I get all kinds of errors when I `export default configureStore`. Although when I do `export default configureStore()` no errors (but still no HMR for redux reducers) – NealVDV Jul 27 '17 at 11:28
1

You will need to import AppContainer and wrap your NextApp container with it.

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

...

...

if (module.hot) {
  module.hot.accept('./client/App', () => {
    const NextApp = './client/App';
    ReactDOM.render(
      <AppContainer />
        <NextApp />
      <AppContainer />,
        rootEl
      );
  });
}

You may need to modify your app.js so that it takes in props

const App = (store, routes) => 
  <Provider store={store}>
    { routes }
  </Provider>;

And then intitialize the store and routes in the index.js, and pass the same store and routes constants as props into <App /> and <NextApp />

I think this issue on the react-reouter-redux repo may help you:

https://github.com/reactjs/react-router-redux/issues/179

Yo Wakita
  • 5,322
  • 3
  • 24
  • 36
0

I was able to use the description by Dan Abramov on "migrating-from-create-react-app" https://github.com/gaearon/react-hot-loader#migrating-from-create-react-app where I set this up on a Raspberry Pi (raspbian) with that popular 7 inch LCD touch screen.

To add an extra twist I used the 'netatalk' file system sharing to have the Raspbian file system show up as a Volume on OSX so I could edit the app source in the Atom editor on the Macbook while the app is running on Raspberry. When I edit source in Atom and save the file, the app then becomes recompiled on Raspberry and the Hot Module Replacement displays the change on the Raspberry LCD without refresh effects. Raspberry isn´t top performance so it takes a few seconds for the change to occur, but way cool.

The real wizards could try to take this further to have the source become compiled on the Macbook (which has more CPU power) and where compiled code still runs and HMR updates on the Raspberry. But how would that scheme look in a HMR sense ? I am not sure how I would go about accomplishing that partitioning.

0

I've created a sample repo, that supports HMR with Redux. React and Redux with HMR using create-react-app

KKK
  • 1,652
  • 7
  • 29
  • 49