Steve Lam
Steve Lam

Reputation: 11

Dynamic react hot reload all js files

I would like to hot reload all react components without adding files one by one.

module.hot.accept(['react/a', 'react/b', 'react/c'], function (){})

In my project I am using require.context to get all js files to hot reload.

'user strict';
import React from 'react';
import ReactDOM from 'react-dom';
import A from 'a'

ReactDOM.render(<A/>, document.getElementById('hello'))
var context = require.context("react", true, /\.js$/);
if (module.hot) {
  module.hot.accept(context.id, function () {
    var reloadedContext = require.context("react", true, /\.js$/);
    ReactDOM.render(<A/>, document.getElementById('hello'))
  });
}

but since I imported A from 'a', file a.js is no longer hot-reloadable. whilst file b.js and c.js is remain hot-reloadable.

I am not sure how require.context work, and why the imported files is not hot-reloadable.

Here is my example project, you can fork and replicate my issue. Please give me some advice thanks!

https://github.com/flik930/webpack-hot-module-reload-with-context-example

Upvotes: 1

Views: 1222

Answers (1)

I cloned your repo and tried your app and for me, hot reloading is working fine, i.e. when I changed component A's text and saved the file, the browser updated. Not sure what has been happening on your machine. Do you want to retry?

EDIT: The page actually reloads when changing A which defeats the purpose of hot module reload...

A solution that seems to work is to use require.context to load the component again, as below:

import React from 'react';
import ReactDOM from 'react-dom';

const context = require.context("react", true, /\.js$/);
const requireA = context => context(context.keys().find(key => key.match(/\/a\.js$/))).default
let A = requireA(context)

ReactDOM.render(<A/>, document.getElementById('hello'))
if (module.hot) {
  module.hot.accept(context.id, function () {
    const reloadedContext = require.context("react", true, /\.js$/);
    A = requireA(reloadedContext)
    ReactDOM.render(<A/>, document.getElementById('hello'))
  });
}

However you'd want to hide this complexity into a separate module so as to make the import transparent (probably in a react/index.js or components/index.js module)

See the React ARC project for examples of such a technique. For instance, this file uses such a technique: https://github.com/diegohaz/arc/blob/master/src/components/index.js

Upvotes: 1

Related Questions