gaearon / react-hot-loader

Tweak React components in real time. (Deprecated: use Fast Refresh instead.)
http://gaearon.github.io/react-hot-loader/
MIT License
12.26k stars 801 forks source link

Reloading class modules results in class being called as a function and throwing an error #1000

Open DingoEatingFuzz opened 6 years ago

DingoEatingFuzz commented 6 years ago

Description

When a transpiled ES6 class is reloaded, it is called as a function. This results in an error

Uncaught (in promise) TypeError: Cannot call a class as a function
    at _classCallCheck (scatterplot-layer.js:5)
    at ScatterplotLayer (scatterplot-layer.js:71)
    at ProxyFacade (react-hot-loader.development.js:647)
    at ReactCompositeComponent.js:303
    at measureLifeCyclePerf (ReactCompositeComponent.js:73)
    at ReactCompositeComponentWrapper._constructComponentWithoutOwner (ReactCompositeComponent.js:302)
    at ReactCompositeComponentWrapper._constructComponent (ReactCompositeComponent.js:277)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:185)
    at Object.mountComponent (ReactReconciler.js:43)
    at Object.updateChildren (ReactChildReconciler.js:119)

It looks like there is already code to circumvent this issue if the module is a React Component class:

https://github.com/gaearon/react-hot-loader/blob/2ec25210c8a2704a9a0818a49c1f897c3e579e86/src/proxy/createClassProxy.js#L114

But not all class modules are React components. I ran into this using deck.gl ScatterplotLayer.

Expected behavior

This module should be called like new Component(...) instead of plain Component().

Actual behavior

This module falls into the isFunctionalComponent code path and throws a runtime error due to the transpiler typechecking.

Environment

React Hot Loader version: 4.2.0

Run these commands in the project folder and fill in their results:

  1. node -v: 8.11.1
  2. npm -v: 5.6.0

Then, specify:

  1. Operating system: High Sierra
  2. Browser and version: Chrome 66
theKashey commented 6 years ago

Probably there is no way fix it, as long RHL should not be applied to this library at all, as long this is not "React", just mimicking some interfaces.

"Cold" components (https://github.com/gaearon/react-hot-loader/pull/992) should fix it completely, by disabling RHL for this library.

DingoEatingFuzz commented 6 years ago

Cold components sounds awesome! Sounds like the blacklist feature I was looking for 😄

theKashey commented 6 years ago

class ScatterplotLayer extends Layer while Layer extends React.Component I have no idea why you example is failing :(

DingoEatingFuzz commented 6 years ago

Interesting. I'll try to make a repro repo.

theKashey commented 6 years ago

Probably fixed in v4.3.0 Anyway - could be fixed by "cold api", also in 4.3.0

alozytskyi commented 6 years ago

@theKashey not fixed by default in v4.3.0. Also error points not to a library but to the one of constructors of a component, so I'm unsure how excluding a component from hot reloading would help. It'd be the same as disabling the hot loader entirely, because it crashes randomly with different classes.

theKashey commented 6 years ago

Then, I need some example to play with.

hustKiwi commented 5 years ago

I met the same error when upgrading from 4.3.12 to the latest 4.6.3. Everything seems to be fine at version 4.3.12 even though my project is using react 16.6.3.

theKashey commented 5 years ago

Just give me an example to reproduce the error, or open a PR with a failing test.

mqliutie commented 2 years ago

"react-hot-loader": "^4.12.21", "react": "^16.14.0", "react-dom": "^16.14.0"

Still have problems