react-hot-loader: RHL throwing ReferenceErrors when hot-reloading third-party hooks.

Description

👋 Hey folks! I’m having a little trouble with RHL’s hooks support in a little Gatsby project. RHL seems to be injecting code that evaluates the imported hook functions using their reference names in the source code. But since the imports have been transformed by Babel and/or Webpack, there’s nothing in scope that matches. React’s built-in hooks do not seem to be affected.

By way of a contrived example, here’s a silly SFC that uses react-spring:

import { animated, useSpring } from 'react-spring'
import React, { useCallback, useState } from 'react'

function Index() {
  const [thingDone, toggleThingDone] = useState(false)
  const doTheThing = useCallback(() => toggleThingDone(!thingDone), [thingDone])

  const fader = useSpring({ opacity: thingDone ? 1 : 0 })

  return (
    <>
      <animated.h1 style={ fader }>
        You did the thing!
      </animated.h1>
      <button type='button' onClick={ doTheThing }>
        { thingDone ? 'Undo The Thing' : 'Do The Thing' }
      </button>
    </>
  )
}

I dropped the transpiled code into this gist; the relevant hunks seem to be line 22:

var _reactSpring = __webpack_require__(/*! react-spring */ "./node_modules/react-spring/web.js");

…lines 42–44:

const fader = (0, _reactSpring.useSpring)({
  opacity: thingDone ? 1 : 0
});

…and line 63:

__signature__(Index, "useState{[thingDone, toggleThingDone]}\nuseCallback{doTheThing}\nuseSpring{fader}", () => [useSpring]);

The component uses the transpiled reference as expected, but RHL doesn’t seem to know about it. When a hot update is triggered, it throws a ReferenceError:

Stack trace :boom:
    
Uncaught ReferenceError: useSpring is not defined
      at Object.getCustomHooks (index.js:5)
      at haveEqualSignatures (react-hot-loader.development.js:2349)
      at areSignaturesCompatible (react-hot-loader.development.js:2370)
      at compareRegistered (react-hot-loader.development.js:2384)
      at compareComponents (react-hot-loader.development.js:2395)
      at hotComponentCompare (react-hot-loader.development.js:2468)
      at reconcileSingleElement (react-dom.development.js:12507)
      at reconcileChildFibers (react-dom.development.js:12589)
      at reconcileChildren (react-dom.development.js:14411)
      at finishClassComponent (react-dom.development.js:14759)
      at updateClassComponent (react-dom.development.js:14697)
      at beginWork (react-dom.development.js:15645)
      at performUnitOfWork (react-dom.development.js:19313)
      at workLoop (react-dom.development.js:19353)
      at renderRoot (react-dom.development.js:19436)
      at performWorkOnRoot (react-dom.development.js:20343)
      at performWork (react-dom.development.js:20255)
      at performSyncWork (react-dom.development.js:20229)
      at requestWork (react-dom.development.js:20098)
      at scheduleWork (react-dom.development.js:19912)
      at Object.enqueueForceUpdate (react-dom.development.js:11209)
      at ExportedComponent../node_modules/react/cjs/react.development.js.Component.forceUpdate (react.development.js:353)
      at react-hot-loader.development.js:2740
      at Array.forEach (<anonymous>)
      at react-hot-loader.development.js:2739
  (anonymous) @ index.js:5
  haveEqualSignatures @ react-hot-loader.development.js:2349
  areSignaturesCompatible @ react-hot-loader.development.js:2370
  compareRegistered @ react-hot-loader.development.js:2384
  compareComponents @ react-hot-loader.development.js:2395
  hotComponentCompare @ react-hot-loader.development.js:2468
  reconcileSingleElement @ react-dom.development.js:12507
  reconcileChildFibers @ react-dom.development.js:12589
  reconcileChildren @ react-dom.development.js:14411
  finishClassComponent @ react-dom.development.js:14759
  updateClassComponent @ react-dom.development.js:14697
  beginWork @ react-dom.development.js:15645
  performUnitOfWork @ react-dom.development.js:19313
  workLoop @ react-dom.development.js:19353
  renderRoot @ react-dom.development.js:19436
  performWorkOnRoot @ react-dom.development.js:20343
  performWork @ react-dom.development.js:20255
  performSyncWork @ react-dom.development.js:20229
  requestWork @ react-dom.development.js:20098
  scheduleWork @ react-dom.development.js:19912
  enqueueForceUpdate @ react-dom.development.js:11209
  ./node_modules/react/cjs/react.development.js.Component.forceUpdate @ react.development.js:353
  (anonymous) @ react-hot-loader.development.js:2740
  (anonymous) @ react-hot-loader.development.js:2739
  setTimeout (async)
  updateInstances @ react-hot-loader.development.js:2732
  (anonymous) @ react-hot-loader.development.js:2756
  hotSetStatus @ bootstrap:246
  hotApply @ bootstrap:628
  cb @ process-update.js:76
  (anonymous) @ process-update.js:91
  Promise.then (async)
  check @ process-update.js:90
  ./node_modules/webpack-hot-middleware/process-update.js.module.exports @ process-update.js:52
  processMessage @ client.js:279
  handleMessage @ client.js:139
  handleMessage @ client.js:102
  06:17:01.939 index.js:2177 The above error occurred in the <LocationProvider> component:
      in LocationProvider (created by Context.Consumer)
      in Location (created by Context.Consumer)
      in Router (created by Root)
      in Root (at root.js:90)
      in ThemeProvider (at provider.js:7)
      in Provider (at gatsby-browser.js:21)
      in _default (at app.js:62)

Consider adding an error boundary to your tree to customize error handling behavior. Visit https://fb.me/react-error-boundaries to learn more about error boundaries. stack_frame_overlay_proxy_console @ index.js:2177 logCapturedError @ react-dom.development.js:17118 logError @ react-dom.development.js:17154 update.callback @ react-dom.development.js:18066 callCallback @ react-dom.development.js:16434 commitUpdateEffects @ react-dom.development.js:16473 commitUpdateQueue @ react-dom.development.js:16461 commitLifeCycles @ react-dom.development.js:17384 commitAllLifeCycles @ react-dom.development.js:18737 callCallback @ react-dom.development.js:150 invokeGuardedCallbackDev @ react-dom.development.js:200 invokeGuardedCallback @ react-dom.development.js:257 commitRoot @ react-dom.development.js:18949 (anonymous) @ react-dom.development.js:20419 unstable_runWithPriority @ scheduler.development.js:255 completeRoot @ react-dom.development.js:20418 performWorkOnRoot @ react-dom.development.js:20347 performWork @ react-dom.development.js:20255 performSyncWork @ react-dom.development.js:20229 requestWork @ react-dom.development.js:20098 scheduleWork @ react-dom.development.js:19912 enqueueForceUpdate @ react-dom.development.js:11209 ./node_modules/react/cjs/react.development.js.Component.forceUpdate @ react.development.js:353 (anonymous) @ react-hot-loader.development.js:2740 (anonymous) @ react-hot-loader.development.js:2739 setTimeout (async) updateInstances @ react-hot-loader.development.js:2732 (anonymous) @ react-hot-loader.development.js:2756 hotSetStatus @ bootstrap:246 hotApply @ bootstrap:628 cb @ process-update.js:76 (anonymous) @ process-update.js:91 Promise.then (async) check @ process-update.js:90 ./node_modules/webpack-hot-middleware/process-update.js.module.exports @ process-update.js:52 processMessage @ client.js:279 handleMessage @ client.js:139 handleMessage @ client.js:102

I’m willing to believe this is an issue with Gatsby’s configuration patterns or my particular abuses of Gatsby’s configuration patterns, so I’m working on putting together a lightweight reproduction case. But I wanted to run it by you folks in the meantime to see whether there were any known issues that may be germane.

Let me know if I can do anything to add more color to the problem or help out with a solution! Thanks so much for your insight. ✨

Expected behavior

RHL should invoke hooks with their transpiled references, so as to avoid throwing ReferenceErrors.

Actual behavior

RHL attempts to invoke hooks using their untranspiled references, which are never in scope and throw ReferenceErrors.

Environment

React Hot Loader version: v4.11.0

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

  1. node -v: v12.4.0
  2. npm -v: v6.9.0
  3. yarn -v’: v1.16.0

Then, specify:

  1. Operating system: macOS 10.15 (19A471t)
  2. Browser and version: Chrome 76.0.3809.21

Reproducible Demo

🚧 So far just the gist, but I’m working on it!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 31 (16 by maintainers)

Commits related to this issue

Most upvoted comments

v4.11.2, or, better, v4.12 should solve the problem

v.4.11.1 released. Containing fixes both for your problem and react-spring. https://github.com/gaearon/react-hot-loader/releases/tag/v4.11.1