Skip to content
This repository has been archived by the owner on Sep 10, 2022. It is now read-only.

[HMR] lifecycle and hot module reload #565

Open
Darmikon opened this issue Nov 17, 2017 · 6 comments
Open

[HMR] lifecycle and hot module reload #565

Darmikon opened this issue Nov 17, 2017 · 6 comments

Comments

@Darmikon
Copy link

Hi guys. HMR works with errors in case I add lifecycle hoc to my container.
It can't save component's state but works for redux store.
I see such error in console

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: 
 ƒ Lifecycle() {
        classCallCheck(this, Lifecycle);
        return possibleConstructorReturn(this, _Component.apply(this, arguments));
      }

component code

const HomeComponent = ()=>(<div>...</div>);

export default compose(
  withState('update', 'setUpdate', false),
  lifecycle({
    componentWillReceiveProps() {
      // ...
    }
  })
)(HomeComponent);

HMR works and redux store is saved during reload but component's state is lost.

@wuct
Copy link
Contributor

wuct commented Nov 19, 2017

Do you mind to create a minimized repo to reproduce your issue? It's will let other people fix it more easily.

@Darmikon
Copy link
Author

@wuct Hi. I've created repo to reproduce this bug.
repo with bug link

Here is steps how to reproduce:

  1. yarn install

  2. yarn start

  3. http://localhost:3000 - click button "Trigger async action"

  4. it will update redux store -> home/username: 'username'

  5. it will update HomeComponent internal state -> updated: true
    (you can open react inspector and see that it's true)

  6. open containers/home.js lines 12-14

  7. go to line 13
    and try to add several zzz letters to console.info('HMR bugz');
    You will see that component was reloaded and console message shows new text.
    Also you'll see that react state is the same for HomeComponent and redux store also is the same.
    No errors in console. And it's fine.

  8. Now comment method componentWillUpdate: lines12-14 and uncomment recompose:lifecycle lines 29-33

  9. Reload browser. And repeat steps: 3, 4, 5.

  10. Now go to line 31
    and try to add several zzz letters to console.info('HMR bugz');

  11. You will see error message in console. Redux store is saved but react state is lost.

I like your library very much but currently I can't use lifecycle method and It would be great if lifecycle method doesn't break HMR work.
Hope it's possible to fix.

Thanks in advance.

@Darmikon
Copy link
Author

In addition. I've just noticed that such error happens when I use more than 1 function in compose. And in the next example withHandlers - update2 hasn't been updated during hmr if I add some letters to console.info and only browser reload helps to see updated version of this method.

export default compose(
  withHandlers({
    update2: props => () => {
      console.info('update');
    }
  }),
  withState('update', 'setUpdate', false),
)(HomeComponent);

Without HMR everything works perfect. Maybe there is some advanced way how to enforce HMR works with this functions.

@AlexChalk
Copy link

I'm getting a similar error with react hot loader, and webpack tells me the culprit is recompose's shouldUpdate().

Error Message:

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: 
 ƒ ShouldUpdate() {
        _classCallCheck(this, ShouldUpdate);

        return _possibleConstructorReturn(this, _Component.apply(this, arguments));
      }

Source:

'use strict';

exports.__esModule = true;

var _react = require('react');

var _setDisplayName = require('./setDisplayName');

var _setDisplayName2 = _interopRequireDefault(_setDisplayName);

var _wrapDisplayName = require('./wrapDisplayName');

var _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var shouldUpdate = function shouldUpdate(test) {
  return function (BaseComponent) {
    var factory = (0, _react.createFactory)(BaseComponent);

    var ShouldUpdate = function (_Component) {
      _inherits(ShouldUpdate, _Component);

      function ShouldUpdate() {
        _classCallCheck(this, ShouldUpdate);

        return _possibleConstructorReturn(this, _Component.apply(this, arguments));
      }

      ShouldUpdate.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
        return test(this.props, nextProps);
      };

      ShouldUpdate.prototype.render = function render() {
        return factory(this.props);
      };

      return ShouldUpdate;
    }(_react.Component);

    if (process.env.NODE_ENV !== 'production') {
      return (0, _setDisplayName2.default)((0, _wrapDisplayName2.default)(BaseComponent, 'shouldUpdate'))(ShouldUpdate);
    }
    return ShouldUpdate;
  };
};

exports.default = shouldUpdate;


//////////////////
// WEBPACK FOOTER
// ./node_modules/recompose/shouldUpdate.js
// module id = 1366
// module chunks = 2

@wuct
Copy link
Contributor

wuct commented Dec 3, 2017

Thanks for the repository and sorry for the late reply. I'll find some time to look into it.

@edoardo-bluframe
Copy link

@wuct Did you?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants