Only top-level component hot reloads #281

Closed
benwiley4000 opened this Issue May 3, 2016 · 23 comments

Comments

Projects
None yet
10 participants
@benwiley4000

benwiley4000 commented May 3, 2016

ETA: This issue actually does involve React Router, after all. Please see my comment further down the thread.

Previously:

I'm using 3.0.0-beta.1.

I originally thought the problem was with React Router but I'm updating the description to reflect what my problem actually is. React Router is fine.

Hot module reloading works for my root component and for any lower level components defined within the same module. However, hot module loading doesn't seem to propagate down the import tree. Lower level components defined in separate files end up triggering the warning message, The following modules couldn't be hot updated: (They would need a full reload!).

Not sure what I'm doing wrong. Here's how I'm telling webpack to re-render.

if (module.hot) {
  module.hot.accept('./root', () => {
    const NextRoot = require('./root').default;
    render(
      <AppContainer>
        <NextRoot {...{ store, history, onUpdate, routes }} />
      </AppContainer>,
      document.getElementById('app')
    );
  });
}

@benwiley4000 benwiley4000 changed the title from Components not hot updating with React Router in hot loader v3 to Only top-level component hot reloads May 3, 2016

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon May 3, 2016

Owner

Please provide a complete example reproducing this. Since it doesn’t happen in gaearon/react-hot-boilerplate#61, it’s hard to say what’s going on.

Owner

gaearon commented May 3, 2016

Please provide a complete example reproducing this. Since it doesn’t happen in gaearon/react-hot-boilerplate#61, it’s hard to say what’s going on.

@gaearon gaearon added the unconfirmed label May 3, 2016

@gaearon gaearon added this to the v3.0 milestone May 3, 2016

@kiki-le-singe

This comment has been minimized.

Show comment
Hide comment
@kiki-le-singe

kiki-le-singe May 3, 2016

Contributor

I get this warning (The following modules couldn't be hot updated: (They would need a full reload!)) too.
It seems be related to react-router and react-hot-loader but I don't know why. My full project on implement_react_hot_loader

package.json

  "scripts": {
    "start": "npm run dev",
    "dev": "DEBUG=app:* babel-node -- server/server.dev.js",
    ...
  }

server.dev.js

import express from 'express';
import webpack from 'webpack';
import path from 'path';
import _debug from 'debug';

import routes from './routes';
import webpackDevMiddleware from './middleware/webpack-dev';
import webpackHotMiddleware from './middleware/webpack-hot';
import projectConfig from '../config';
import webpackConfig from '../webpack/dev.config.js';

const debug = _debug('app:server');
const app = express();
const compiler = webpack(webpackConfig);


app.use(express.static(path.resolve('src/assets')));

/* *******************
webpack configuration
******************* */

app.use(webpackDevMiddleware(compiler, webpackConfig.output.publicPath));
app.use(webpackHotMiddleware(compiler));


/* ******************
 ROUTES FOR OUR API
******************* */

routes(app);


/* ****************
 START THE SERVER
***************** */

app.listen(projectConfig.SERVER_PORT, () => {
  debug(`Express server listening on ${projectConfig.SERVER_PORT} in ${app.settings.env} mode`);
});

webpack/dev.config.js

import webpack from 'webpack';
import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import _debug from 'debug';

import projectConfig, { paths } from '../config';

const debug = _debug('app:webpack:config:dev');
const srcDir = paths('src');
const assetsDir = paths('assets');
const nodeModulesDir = paths('nodeModules');

const deps = [
  'redux/dist/redux.min.js',
  'font-awesome/css/font-awesome.min.css',
  'slideout/dist/slideout.min.js',
];

debug('Create configuration.');
const config = {
  devtool: 'cheap-module-eval-source-map',
  entry: {
    app: [
      'react-hot-loader/patch',
      'webpack-hot-middleware/client?reload=true',
      paths('entryApp'),
    ],
    vendors: projectConfig.VENDOR_DEPENDENCIES,
  },
  output: {
    path: '/',
    filename: '[name]-[hash].js',
    publicPath: '/',
  },
  resolve: {
    alias: {},
    root: [srcDir],
    extensions: ['', '.js', '.jsx'],
  },
  module: {
    noParse: [],
    preLoaders: [
      {
        test: /\.js[x]?$/,
        loader: 'eslint',
        include: [srcDir],
      },
    ],
    loaders: [
      {
        test: /\.js[x]?$/,
        loader: 'babel',
        query: {
          cacheDirectory: true,
        },
        include: [srcDir],
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
      {
        test: /\.css$/,
        loader: 'style!css!postcss',
      },
      {
        test: /\.(png|jpe?g)$/,
        loader: 'file?name=img/[name].[ext]',
      },
      {
        test: /\.(woff|woff2|eot|ttf|svg)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file?name=fonts/[name].[ext]',
      },
    ],
  },
  postcss: webpack => ([ // eslint-disable-line
    require('postcss-import')({ addDependencyTo: webpack }),
    require('postcss-url')(),
    require('postcss-cssnext')(),
  ]),
  plugins: [
    new HtmlWebpackPlugin({
      title: 'React Redux Boilerplate',
      hash: true,
      favicon: path.resolve(assetsDir, 'favicon.ico'),
      inject: 'body',
      template: path.resolve(srcDir, 'index.tpl.html'),
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.CommonsChunkPlugin('vendors', '[name].[hash].js'),
    new webpack.DefinePlugin({
      __CLIENT__: projectConfig.__CLIENT__,
      __SERVER__: projectConfig.__SERVER__,
      __DEV__: projectConfig.__DEV__,
      __PROD__: projectConfig.__PROD__,
      __DEBUG__: projectConfig.__DEBUG__,
    }),
    new webpack.optimize.DedupePlugin(),
  ],
};

deps.forEach(dep => {
  const depPath = path.resolve(nodeModulesDir, dep);

  config.resolve.alias[dep.split(path.sep)[0]] = depPath;
  config.module.noParse.push(depPath);
});

export default config;

src/routes/index.js

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

import AppLayout from 'layouts/AppLayout';
import Home from 'components/views/Home';
import About from 'components/views/About';
import Hello from 'components/views/Hello';
import Counter from 'components/views/Counter';
import Tools from 'components/views/Tools';
import Tool from 'components/views/Tools/Tool';
import NotFound from 'components/views/NotFound';

export default (
  <Route path="/" component={AppLayout}>
    <IndexRoute component={Home} />
    <Route path="home" component={Home} />
    <Route path="hello" component={Hello} />
    <Route path="about" component={About} />
    <Route path="counter" component={Counter} />
    <Route path="tools" component={Tools} />
    <Route path="tool/:id/:slug" component={Tool} />
    <Route path="404" component={NotFound} />
    <Redirect from="*" to="404" />
  </Route>
);

src/index.js

import { AppContainer } from 'react-hot-loader';
import React from 'react';
import ReactDOM from 'react-dom';
import { hashHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

import configureStore from './redux/store';

import Root from 'containers/Root';
import routes from 'routes';

// *** STYLES *** //
// Path to svg logos icons
import 'assets/vendors/icons.svg.css';
import 'styles/app.css';

const rootEl = document.getElementById('root');
const store = configureStore();
// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(hashHistory, store);

ReactDOM.render(
  <AppContainer>
    <Root history={history} store={store} routes={routes} />
  </AppContainer>,
  rootEl
);

if (module.hot) {
  module.hot.accept('containers/Root', () => {
    // If you use Webpack 2 in ES modules mode, you can
    // use <Root /> here rather than require() a <NextRoot />.
    const NextRoot = require('./containers/Root').default;
    ReactDOM.render(
      <AppContainer>
         <NextRoot history={history} store={store} routes={routes} />
      </AppContainer>,
      rootEl
    );
  });
}

src/containers/Root.js

let Root;

if (__DEV__) {
  Root = require('./RootDev').default;
} else {
  Root = require('./RootProd').default;
}

export default Root;

src/containers/RootDev

import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';

import DevTools from './DevTools';

const propTypes = {
  history: PropTypes.object.isRequired,
  store: PropTypes.object.isRequired,
  routes: PropTypes.object.isRequired,
};

function RootDev(props) {
  const { history, store, routes } = props;
  const showDevTools = () => (__DEBUG__ ? (<DevTools />) : false);

  return (
    <Provider store={store}>
      <div className="app">
        <Router history={history} routes={routes} />
        { showDevTools() }
      </div>
    </Provider>
  );
}

RootDev.propTypes = propTypes;

export default RootDev;

Thanks for your help

Contributor

kiki-le-singe commented May 3, 2016

I get this warning (The following modules couldn't be hot updated: (They would need a full reload!)) too.
It seems be related to react-router and react-hot-loader but I don't know why. My full project on implement_react_hot_loader

package.json

  "scripts": {
    "start": "npm run dev",
    "dev": "DEBUG=app:* babel-node -- server/server.dev.js",
    ...
  }

server.dev.js

import express from 'express';
import webpack from 'webpack';
import path from 'path';
import _debug from 'debug';

import routes from './routes';
import webpackDevMiddleware from './middleware/webpack-dev';
import webpackHotMiddleware from './middleware/webpack-hot';
import projectConfig from '../config';
import webpackConfig from '../webpack/dev.config.js';

const debug = _debug('app:server');
const app = express();
const compiler = webpack(webpackConfig);


app.use(express.static(path.resolve('src/assets')));

/* *******************
webpack configuration
******************* */

app.use(webpackDevMiddleware(compiler, webpackConfig.output.publicPath));
app.use(webpackHotMiddleware(compiler));


/* ******************
 ROUTES FOR OUR API
******************* */

routes(app);


/* ****************
 START THE SERVER
***************** */

app.listen(projectConfig.SERVER_PORT, () => {
  debug(`Express server listening on ${projectConfig.SERVER_PORT} in ${app.settings.env} mode`);
});

webpack/dev.config.js

import webpack from 'webpack';
import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import _debug from 'debug';

import projectConfig, { paths } from '../config';

const debug = _debug('app:webpack:config:dev');
const srcDir = paths('src');
const assetsDir = paths('assets');
const nodeModulesDir = paths('nodeModules');

const deps = [
  'redux/dist/redux.min.js',
  'font-awesome/css/font-awesome.min.css',
  'slideout/dist/slideout.min.js',
];

debug('Create configuration.');
const config = {
  devtool: 'cheap-module-eval-source-map',
  entry: {
    app: [
      'react-hot-loader/patch',
      'webpack-hot-middleware/client?reload=true',
      paths('entryApp'),
    ],
    vendors: projectConfig.VENDOR_DEPENDENCIES,
  },
  output: {
    path: '/',
    filename: '[name]-[hash].js',
    publicPath: '/',
  },
  resolve: {
    alias: {},
    root: [srcDir],
    extensions: ['', '.js', '.jsx'],
  },
  module: {
    noParse: [],
    preLoaders: [
      {
        test: /\.js[x]?$/,
        loader: 'eslint',
        include: [srcDir],
      },
    ],
    loaders: [
      {
        test: /\.js[x]?$/,
        loader: 'babel',
        query: {
          cacheDirectory: true,
        },
        include: [srcDir],
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
      {
        test: /\.css$/,
        loader: 'style!css!postcss',
      },
      {
        test: /\.(png|jpe?g)$/,
        loader: 'file?name=img/[name].[ext]',
      },
      {
        test: /\.(woff|woff2|eot|ttf|svg)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file?name=fonts/[name].[ext]',
      },
    ],
  },
  postcss: webpack => ([ // eslint-disable-line
    require('postcss-import')({ addDependencyTo: webpack }),
    require('postcss-url')(),
    require('postcss-cssnext')(),
  ]),
  plugins: [
    new HtmlWebpackPlugin({
      title: 'React Redux Boilerplate',
      hash: true,
      favicon: path.resolve(assetsDir, 'favicon.ico'),
      inject: 'body',
      template: path.resolve(srcDir, 'index.tpl.html'),
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.CommonsChunkPlugin('vendors', '[name].[hash].js'),
    new webpack.DefinePlugin({
      __CLIENT__: projectConfig.__CLIENT__,
      __SERVER__: projectConfig.__SERVER__,
      __DEV__: projectConfig.__DEV__,
      __PROD__: projectConfig.__PROD__,
      __DEBUG__: projectConfig.__DEBUG__,
    }),
    new webpack.optimize.DedupePlugin(),
  ],
};

deps.forEach(dep => {
  const depPath = path.resolve(nodeModulesDir, dep);

  config.resolve.alias[dep.split(path.sep)[0]] = depPath;
  config.module.noParse.push(depPath);
});

export default config;

src/routes/index.js

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

import AppLayout from 'layouts/AppLayout';
import Home from 'components/views/Home';
import About from 'components/views/About';
import Hello from 'components/views/Hello';
import Counter from 'components/views/Counter';
import Tools from 'components/views/Tools';
import Tool from 'components/views/Tools/Tool';
import NotFound from 'components/views/NotFound';

export default (
  <Route path="/" component={AppLayout}>
    <IndexRoute component={Home} />
    <Route path="home" component={Home} />
    <Route path="hello" component={Hello} />
    <Route path="about" component={About} />
    <Route path="counter" component={Counter} />
    <Route path="tools" component={Tools} />
    <Route path="tool/:id/:slug" component={Tool} />
    <Route path="404" component={NotFound} />
    <Redirect from="*" to="404" />
  </Route>
);

src/index.js

import { AppContainer } from 'react-hot-loader';
import React from 'react';
import ReactDOM from 'react-dom';
import { hashHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

import configureStore from './redux/store';

import Root from 'containers/Root';
import routes from 'routes';

// *** STYLES *** //
// Path to svg logos icons
import 'assets/vendors/icons.svg.css';
import 'styles/app.css';

const rootEl = document.getElementById('root');
const store = configureStore();
// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(hashHistory, store);

ReactDOM.render(
  <AppContainer>
    <Root history={history} store={store} routes={routes} />
  </AppContainer>,
  rootEl
);

if (module.hot) {
  module.hot.accept('containers/Root', () => {
    // If you use Webpack 2 in ES modules mode, you can
    // use <Root /> here rather than require() a <NextRoot />.
    const NextRoot = require('./containers/Root').default;
    ReactDOM.render(
      <AppContainer>
         <NextRoot history={history} store={store} routes={routes} />
      </AppContainer>,
      rootEl
    );
  });
}

src/containers/Root.js

let Root;

if (__DEV__) {
  Root = require('./RootDev').default;
} else {
  Root = require('./RootProd').default;
}

export default Root;

src/containers/RootDev

import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';

import DevTools from './DevTools';

const propTypes = {
  history: PropTypes.object.isRequired,
  store: PropTypes.object.isRequired,
  routes: PropTypes.object.isRequired,
};

function RootDev(props) {
  const { history, store, routes } = props;
  const showDevTools = () => (__DEBUG__ ? (<DevTools />) : false);

  return (
    <Provider store={store}>
      <div className="app">
        <Router history={history} routes={routes} />
        { showDevTools() }
      </div>
    </Provider>
  );
}

RootDev.propTypes = propTypes;

export default RootDev;

Thanks for your help

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon May 3, 2016

Owner

Sorry, copy-pasting and setting up a project is really tedious to validate bug reports 😄
Can you please provide this on GitHub?

Owner

gaearon commented May 3, 2016

Sorry, copy-pasting and setting up a project is really tedious to validate bug reports 😄
Can you please provide this on GitHub?

@kiki-le-singe

This comment has been minimized.

Show comment
Hide comment
@kiki-le-singe

kiki-le-singe May 3, 2016

Contributor

Yes I understand :D this is my repo react-redux-boilerplate

Contributor

kiki-le-singe commented May 3, 2016

Yes I understand :D this is my repo react-redux-boilerplate

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 May 3, 2016

I assume you won't need access to the commit history - I created an orphan repo and changed a few things because the other repo I'm working on is private. Here: react-hot-loader-attempt

Webpack configuration and dev server deployment all takes place inside the gulpfile.js between lines 149 and 254.

I'm also getting a strange websocket error when I run a new copy of the project in a different directory:

WebSocket connection to 'ws://localhost:8079/sockjs-node/633/rfhkw1kn/websocket' failed:
Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but
no response was received

I don't think this necessarily has anything to do with React Hot Loader; in fact, the hot reloading that was working (when editing the root component) still works, so I think it's safe to ignore that error for now. But if anyone knows why that is happening please let me know!

I assume you won't need access to the commit history - I created an orphan repo and changed a few things because the other repo I'm working on is private. Here: react-hot-loader-attempt

Webpack configuration and dev server deployment all takes place inside the gulpfile.js between lines 149 and 254.

I'm also getting a strange websocket error when I run a new copy of the project in a different directory:

WebSocket connection to 'ws://localhost:8079/sockjs-node/633/rfhkw1kn/websocket' failed:
Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but
no response was received

I don't think this necessarily has anything to do with React Hot Loader; in fact, the hot reloading that was working (when editing the root component) still works, so I think it's safe to ignore that error for now. But if anyone knows why that is happening please let me know!

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon May 3, 2016

Owner

Thanks for the repro cases. I’ll have a look in a week or two.

Owner

gaearon commented May 3, 2016

Thanks for the repro cases. I’ll have a look in a week or two.

@kiki-le-singe

This comment has been minimized.

Show comment
Hide comment
@kiki-le-singe

kiki-le-singe May 3, 2016

Contributor

OK thanks for your time

Contributor

kiki-le-singe commented May 3, 2016

OK thanks for your time

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 May 18, 2016

@gaeron have you had a chance to look yet?

@gaeron have you had a chance to look yet?

@gaearon

This comment has been minimized.

Show comment
Hide comment
Owner

gaearon commented May 18, 2016

@benwiley4000 Not yet!

@davidlormor

This comment has been minimized.

Show comment
Hide comment
@davidlormor

davidlormor May 31, 2016

So I'm running into some similar issues, and it seems that this may all be related to stateless components tied to routes. Whenever I assign a react-router Route component to a component without any state, that route and all its children do not hot reload. Not really sure what the root cause is (I'm a long time Emberist just getting familiar with React), but I imagine that may put you in the right direction.

Thanks for all y'all's awesome work!

So I'm running into some similar issues, and it seems that this may all be related to stateless components tied to routes. Whenever I assign a react-router Route component to a component without any state, that route and all its children do not hot reload. Not really sure what the root cause is (I'm a long time Emberist just getting familiar with React), but I imagine that may put you in the right direction.

Thanks for all y'all's awesome work!

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 Jun 3, 2016

@davidlormor are you sure this is the problem - have you tried using state with your components to see if that fixes the issue? I'm only asking because I seem to recall experiencing the same issue without React Router in the way (hence my update in the original post), but I also didn't scientifically document my whole trial/error process.

@davidlormor are you sure this is the problem - have you tried using state with your components to see if that fixes the issue? I'm only asking because I seem to recall experiencing the same issue without React Router in the way (hence my update in the original post), but I also didn't scientifically document my whole trial/error process.

@davidlormor

This comment has been minimized.

Show comment
Hide comment
@davidlormor

davidlormor Jun 3, 2016

@benwiley4000 yes, whenever I switch the Route's component from a stateless function to a class-based component the hot reload works, but when I switch it back to a stateless functional component the hot reload fails. (Tried across several routes/components)...it may have nothing to do with the Router, but rather something about stateless components, perhaps...like I mentioned I haven't dived too deep into this issue, just sharing my observations.

@benwiley4000 yes, whenever I switch the Route's component from a stateless function to a class-based component the hot reload works, but when I switch it back to a stateless functional component the hot reload fails. (Tried across several routes/components)...it may have nothing to do with the Router, but rather something about stateless components, perhaps...like I mentioned I haven't dived too deep into this issue, just sharing my observations.

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 Jun 21, 2016

@gaearon I understand you're quite busy. I'd love for you to take another look at this one, if you can. I've been going without hot reloading for the last six weeks and I'd really like to get it working! 😃

benwiley4000 commented Jun 21, 2016

@gaearon I understand you're quite busy. I'd love for you to take another look at this one, if you can. I've been going without hot reloading for the last six weeks and I'd really like to get it working! 😃

@ctrlplusb

This comment has been minimized.

Show comment
Hide comment
@ctrlplusb

ctrlplusb Jun 21, 2016

Contributor

@benwiley4000 try module.hot.accept your routes to cause a reload within your app.js. I had to do this for my case, perhaps it will work for you? Here is my working version: https://github.com/ctrlplusb/react-universally

Contributor

ctrlplusb commented Jun 21, 2016

@benwiley4000 try module.hot.accept your routes to cause a reload within your app.js. I had to do this for my case, perhaps it will work for you? Here is my working version: https://github.com/ctrlplusb/react-universally

@l2silver

This comment has been minimized.

Show comment
Hide comment
@l2silver

l2silver Jul 23, 2016

@davidlormor I think it is react-router. I'm dealing with a similar issue. Checkout the following...

hmr fails

<Route component={()=><p>Hello</p>}

hmr works

class SimpleComponent extends Component {
 render(){
  return <p>Hello</p>
 }
}
<Route component={SimpleComponent} />

hmr also works

class SimpleComponent extends Component {
 render(){
 return <SimpleStatelessComponent />
 }
}

function SimpleStatelessComponent(){
 return <p>Hello</p>
}
<Route component={SimpleComponent} />

@davidlormor I think it is react-router. I'm dealing with a similar issue. Checkout the following...

hmr fails

<Route component={()=><p>Hello</p>}

hmr works

class SimpleComponent extends Component {
 render(){
  return <p>Hello</p>
 }
}
<Route component={SimpleComponent} />

hmr also works

class SimpleComponent extends Component {
 render(){
 return <SimpleStatelessComponent />
 }
}

function SimpleStatelessComponent(){
 return <p>Hello</p>
}
<Route component={SimpleComponent} />

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 Aug 19, 2016

@l2silver I tried as hard as I could to reproduce the behavior you claimed worked for you, but I could not. I switched my route components to class components and I still could not get HMR to work.

I'm getting the error (as mentioned before): The following modules couldn't be hot updated: (They would need a full reload!).

@ctrlplusb To be honest I don't understand how that would solve the problem at hand. Still I was curious. This was my code before:

if (module.hot) {
  module.hot.accept('./root', () => {
    const NextRoot = require('./root').default;
    render(
      <AppContainer>
        <NextRoot {...{ store, history, onUpdate, routes }} />
      </AppContainer>,
      document.getElementById('app')
    );
  });
}

And I changed it to:

if (module.hot) {
  module.hot.accept(['./root', './route'], () => {
    // ...
  });
}

There was a difference - I no longer get the above warning, but still, nothing reloads. 😞 I also tried accepting only './routes' and I had the same result. What was your before / after?

@gaearon I would really, really, really appreciate you taking a look at the sample repo I provided you. Thanks. :)

benwiley4000 commented Aug 19, 2016

@l2silver I tried as hard as I could to reproduce the behavior you claimed worked for you, but I could not. I switched my route components to class components and I still could not get HMR to work.

I'm getting the error (as mentioned before): The following modules couldn't be hot updated: (They would need a full reload!).

@ctrlplusb To be honest I don't understand how that would solve the problem at hand. Still I was curious. This was my code before:

if (module.hot) {
  module.hot.accept('./root', () => {
    const NextRoot = require('./root').default;
    render(
      <AppContainer>
        <NextRoot {...{ store, history, onUpdate, routes }} />
      </AppContainer>,
      document.getElementById('app')
    );
  });
}

And I changed it to:

if (module.hot) {
  module.hot.accept(['./root', './route'], () => {
    // ...
  });
}

There was a difference - I no longer get the above warning, but still, nothing reloads. 😞 I also tried accepting only './routes' and I had the same result. What was your before / after?

@gaearon I would really, really, really appreciate you taking a look at the sample repo I provided you. Thanks. :)

@starInEcust

This comment has been minimized.

Show comment
Hide comment
@starInEcust

starInEcust Aug 31, 2016

hi guys,how's it going?
my component extends another component like this
class InnerQuery extends DelayRenderComponent
get the same error
the following modules couldn't be hot updated: (They would need a full reload!).

hi guys,how's it going?
my component extends another component like this
class InnerQuery extends DelayRenderComponent
get the same error
the following modules couldn't be hot updated: (They would need a full reload!).

@Kinjeiro

This comment has been minimized.

Show comment
Hide comment
@Kinjeiro

Kinjeiro Sep 22, 2016

@starInEcust The same problem. If inner component extends any non react Component, hot reload willn't work - page will be full reloaded

It's major bug (component's hierarchy is usefull functionality), please, fix it

Kinjeiro commented Sep 22, 2016

@starInEcust The same problem. If inner component extends any non react Component, hot reload willn't work - page will be full reloaded

It's major bug (component's hierarchy is usefull functionality), please, fix it

@calesce

This comment has been minimized.

Show comment
Hide comment
@calesce

calesce Sep 22, 2016

Collaborator

@starInEcust: can you open a separate issue for extending other components? A project reproducing the issue would be extremely helpful, as well.

@Kinjeiro: we are all working on this in our spare time, telling maintainers to "fix it" is unhelpful.

Collaborator

calesce commented Sep 22, 2016

@starInEcust: can you open a separate issue for extending other components? A project reproducing the issue would be extremely helpful, as well.

@Kinjeiro: we are all working on this in our spare time, telling maintainers to "fix it" is unhelpful.

@vdh

This comment has been minimized.

Show comment
Hide comment
@vdh

vdh Sep 22, 2016

@starInEcust @Kinjeiro AFAIK, there's no mention in the React docs about inheritance, you may be attempting to use an unsupported workflow. They advocate "composition over inheritance".

vdh commented Sep 22, 2016

@starInEcust @Kinjeiro AFAIK, there's no mention in the React docs about inheritance, you may be attempting to use an unsupported workflow. They advocate "composition over inheritance".

@Kinjeiro

This comment has been minimized.

Show comment
Hide comment
@Kinjeiro

Kinjeiro Sep 23, 2016

@calesce I'm sorry for my tone, thank you for this wonderful plugin

@vdh thank you for idea. Need think about litle refactoring =)

@calesce I'm sorry for my tone, thank you for this wonderful plugin

@vdh thank you for idea. Need think about litle refactoring =)

@benwiley4000

This comment has been minimized.

Show comment
Hide comment
@benwiley4000

benwiley4000 Sep 25, 2016

@gaearon I spent a very long time tonight debugging this issue further to land on precisely what my problem is. It turns out, I was correct the first time, and this is a React Router issue. And in fact it's the same issue you have already identified here and here.

I was led to believe it was merely an import issue, but it turns out that imported components hot swap fine if they are included outside of a Router instance. I have also found that hot swapping works fine with React Router if everything the Router instance uses is defined in the same file as that Router instance. The Router itself can live in its own file and be imported to the root, but all Route instances and component definitions must live in the same file as Router, and hot reloading works. Obviously not practical for any real application.

I do have a follow-up question but it pertains to React Router so it's in this thread.

benwiley4000 commented Sep 25, 2016

@gaearon I spent a very long time tonight debugging this issue further to land on precisely what my problem is. It turns out, I was correct the first time, and this is a React Router issue. And in fact it's the same issue you have already identified here and here.

I was led to believe it was merely an import issue, but it turns out that imported components hot swap fine if they are included outside of a Router instance. I have also found that hot swapping works fine with React Router if everything the Router instance uses is defined in the same file as that Router instance. The Router itself can live in its own file and be imported to the root, but all Route instances and component definitions must live in the same file as Router, and hot reloading works. Obviously not practical for any real application.

I do have a follow-up question but it pertains to React Router so it's in this thread.

@calesce

This comment has been minimized.

Show comment
Hide comment
@calesce

calesce Sep 26, 2016

Collaborator

Glad you found out what was going on, @benwiley4000. Sorry none of us got back to you. It's clear that we need to document the known issues with RR 2/3, right now the solutions/workarounds are scattered in other issue threads. I'm going to close this one since we're tracking this in #249.

Collaborator

calesce commented Sep 26, 2016

Glad you found out what was going on, @benwiley4000. Sorry none of us got back to you. It's clear that we need to document the known issues with RR 2/3, right now the solutions/workarounds are scattered in other issue threads. I'm going to close this one since we're tracking this in #249.

@calesce calesce closed this Sep 26, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment