react-hot-loader: HotLoader won't work after adding >=2 levels of HoC.

Way to reproduce the issue:

import React, { Component } from 'react';

export function provideHoC() {
  return WrappedComponent => {
    class HoC extends Component {
      render() {
        return <WrappedComponent {...this.props} />
      }
    }

    HoC.displayName = (WrappedComponent.displayName || WrappedComponent.name) + 'WithHOC';
    return HoC;
  };
}
  • Modify src/Counter.js
 import React, { Component } from 'react';
+import { provideHoC } from './HoC';

-export default class Counter extends Component {
+class Counter extends Component {
   constructor(props) {
    super(props);
    this.state = { counter: 0 };
  }

  componentDidMount() {
    this.interval = setInterval(this.tick.bind(this), 1000);
  }

  tick() {
    this.setState({ counter: this.state.counter + 1 });
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <h2>Counter: {this.state.counter}</h2>;
  }
}
+
+export default provideHoC()(provideHoC()(Counter));
  • npm start and go to http://localhost:3000.
  • Modify some text inside render method of Counter.
  • The counter state will be gone.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 25

Most upvoted comments

Hard to fix on huge projects with tons of nested HoCs (since it is proper way to do HoCs). I created babel plugin to solve this: https://www.npmjs.com/package/extract-hoc

Due to internal logic, all spare parts (ie hot-replaceable) must be extracted as top-level variables, or HRL will not be able to hot-swap them. This is a stopper for HoC or decorators. It is just easier to convert HOCs to a normal, prop-based components, and use react, not functional composition, to create target logic. Or just use

 const level1 = provideHoC()(Counter);
 const level2 = provideHoC()(level1);
 export default level2;

A long issue finally fixed in React Hot Loader v4.

Here are the errors I get:

React Hot Loader: this component is not accepted by Hot Loader. 
Please check is it extracted as a top level class, a function or a variable. 
Click below to reveal the source location: 
 ƒ Connect(props, context) {
        _classCallCheck(this, Connect);

        var _this = _possibleConstructorReturn(this, _Component.call(this, props, context));

        _this.version = version;
     …
React Hot Loader: this component is not accepted by Hot Loader. 
Please check is it extracted as a top level class, a function or a variable. 
Click below to reveal the source location: 
 ƒ Form() {
          var _ref;

          var _temp, _this, _ret;

          _classCallCheck(this, Form);

          for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++)…

Still running into this issue, even after using extra-hoc babel plugin and manually extracting HoCs into separate components

Package.json: https://github.com/blazing-edge-labs/admin-playground/blob/master/package.json Component with HoCs: https://github.com/blazing-edge-labs/admin-playground/blob/master/src/modules/Examples/Profile/Edit/index.js

Decorators will not work at all. There is no way to make them work. Except #711 - it will literally solve everything. I’ll do my best to make v4 sorted out before Christmas.

https://github.com/quangbuule/extract-hoc solved this issue for me for react-apollo and react-redux HOCs. Would be great if this was integrated somehow.