facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
229.04k stars 46.86k forks source link

Fast Refresh: Improve dev experience when DevTools hook is disabled #20117

Closed Sinsstranger closed 3 years ago

Sinsstranger commented 4 years ago

The crash is likely being caused by some third party code (possibly a browser extension) injecting a partial DevTools hook into the page. (See below comments for more information.)

We can't prevent this but Fast Refresh could more gracefully handle this case by checking to see if window. __REACT_DEVTOOLS_GLOBAL_HOOK__.isDisabled is true (like we do here). Rather than crash, Fast Refresh could print a warning to the console in DEV mode saying that it won't run because of the disabled hook override.


Original report: Crash with "hook.renderers is undefined"


I have a bit problem, when i just do yarn create react-app name --template redux, and start it to learn how to develop - I saw next: On localhost(it's vmware virtualhost) I have no problem, but on host machine i see Uncaught TypeError: hook.renderers is undefined in js console, and empty body 2020-10-28_17-49-42 How can I handle it? And what this error means in general?

bvaughn commented 4 years ago

What browser extensions are installed on your local machine? It seems like something else might be interfering with the window.__REACT_DEVTOOLS_GLOBAL_HOOK__ variable. The expectation is that either React DevTools (v4+) or the Fast Refresh runtime will be the only thing that create or use that hook.

https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-devtools-shared/src/backend/index.js#L90-L93

https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-refresh/src/ReactFreshRuntime.js#L482-L485

DevTools initializes the hook with a renderers map specifically for Fast Refresh: https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-devtools-shared/src/hook.js#L313-L325

Fast Refresh does the same if DevTools wasn't around to initialize the hook: https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-refresh/src/ReactFreshRuntime.js#L439-L442

So my guess is that you have some other extension installed (possibly even a really old version of React DevTools?) that's initializing window.__REACT_DEVTOOLS_GLOBAL_HOOK__ first but not properly setting up the renderers map.

Sinsstranger commented 4 years ago

I have set up the React DevTools 4.9.0(last version) - to my host machine, and now i have no problem on it, on virtual machine then I have my dev envirironment(phpstorm, create-react app etc.) I have no problem as erlier. Indeed all problem was in the DevTools didn't installed on my host machine?! (excause me for my bad english). I checked it and I saw that problem was in it!

bvaughn commented 4 years ago

Indeed all problem was in the DevTools didn't installed on my host machine?

No. The React DevTools extension should not be required. Fast Refresh will check to see if DevTools isn't installed and will initialize the hook itself: https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-refresh/src/ReactFreshRuntime.js#L439-L466

My guess was that something else (another extension?) was initializing the hook so that this Fast Refresh check didn't pass: https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-refresh/src/ReactFreshRuntime.js#L442

But this line later throws: https://github.com/facebook/react/blob/779a472b0901b2d28e382f3850b2ad09a555b014/packages/react-refresh/src/ReactFreshRuntime.js#L485

bvaughn commented 4 years ago

@Sinsstranger Can you reproduce this error in an incognito window (with all extensions disabled)?

Sinsstranger commented 4 years ago

Yes i have this problem with it bouth incognito, and not incognito mode with all extensions disabled

gaearon commented 4 years ago

@Sinsstranger If you log window.__REACT_DEVTOOLS_GLOBAL_HOOK__, what do you see? My guess is that you're using some hack to disable React DevTools in production (e.g. by assigning an empty object to it), which in turn causes this issue.

Sinsstranger commented 4 years ago

On localhost(it's virtual machine) where I learn React without some extensions I have no problem console.log(window.REACT_DEVTOOLS_GLOBAL_HOOK__) returns localhost_without_some_extensions On PC in Local Network(it's machine with vmware workstation, and on it I have virtual machine where I learn React) without extension reactDevTools I have our problem console.log(window.REACT_DEVTOOLS_GLOBAL_HOOK) returns From_LocalNetwork_Machine_withOut_ReactDevTools_Extension And with ReactDevTools on it I have no problem and console.log(window.__REACT_DEVTOOLS_GLOBAL_HOOK) returns From_LocalNetwork_Machine_with_ReactDevTools_Extension

bvaughn commented 4 years ago

On PC in Local Network(it's machine with vmware workstation, and on it I have virtual machine where I learn React) without extension reactDevTools I have our problem console.log(window.REACT_DEVTOOLS_GLOBAL_HOOK) returns

The output logged by this machine does not look like anything we (React or DevTools) inject. Something else is setting the value of __RECT_DEVTOOLS_GLOBAL_HOOK__.

Can you add this code to your app (at the top, before other scripts are loaded) and see if it logs anything?

let hook;
Object.defineProperty(window, '__REACT_DEVTOOLS_GLOBAL_HOOK__', {
  get() {
    return hook;
  },
  set(value) {
    console.trace('hook initialized:', value);
    hook = value;
  }
});
gaearon commented 4 years ago

Do you use React with any third-party renderers?

VoliBearCat commented 4 years ago

I has same problem, update the React DevTools extensions version and fixed it

bvaughn commented 4 years ago

@VoliBearCat Maybe you were using v3 of DevTools? Browsers should auto-update the extension though, and v4 has defined a renderers prop for a couple of years.

The value logged above doesn't even look like the hook that v3 used though, except that it defines an inject method. To me, this looks like another extension (or some other infra) pretending to be React DevTools (and doing an incomplete version of it).

bvaughn commented 4 years ago

Maybe something intentionally trying to block the (DEV only) console log telling people to install the DevTools extension? The fact that there's an isDisabled property kind of confirms that. That's not a property that is set by the real DevTools hook but it is something that React checks for and honors as an opt-out mechanism.

bvaughn commented 4 years ago

@gaearon Should Fast Refresh check the isDisabled prop too and maybe print a DEV warning/explanation if it's around?

gaearon commented 4 years ago

Sure, happy to take a PR if someone wants to make it.

VoliBearCat commented 4 years ago

@VoliBearCat Maybe you were using v3 of DevTools? Browsers should auto-update the extension though, and v4 has defined a renderers prop for a couple of years.

The value logged above doesn't even look like the hook that v3 used though, except that it defines an inject method. To me, this looks like another extension (or some other infra) pretending to be React DevTools (and doing an incomplete version of it).

I recently used Fast Refresh. my co-worker didn't use VPN so she can't update extensions from google. we reside in China. :-P

bvaughn commented 4 years ago

Makes sense. Hope you like the new DevTools! :smile:

Here's a guide that explains some of the things that changed between v3 and v4: https://github.com/facebook/react/blob/master/packages/react-devtools/CHANGELOG.md#400-august-15-2019

And here's an interactive tutorial: https://react-devtools-tutorial.now.sh/

AceTheCreator commented 4 years ago

Is anybody working on this issue? I will love to take it.

bvaughn commented 4 years ago

@alphabet-codes No one has started it to my knowledge. (If they had, there would be a comment on this issue.) Feel free!

Check out my updated description for what I think is the desired outcome now.

mrfambo commented 4 years ago

@bvaughn Can i fix this issue? I have already started working on it though 😆

(P.S: Do we need to have a test case for it? If yes, i will have to possibly add a new test file with partial devtools injected and expecting a warning in console)

mrfambo commented 4 years ago

As per "How to contribute", i am leaving a comment that i am working on this issue 😸 @alphabet-codes , If you are working on it, i will surely backoff ❤️

bvaughn commented 4 years ago

Test case would be nice.

AceTheCreator commented 4 years ago

@mrfambo I'm currently working on this. Thanks for the attention.

mrfambo commented 4 years ago

@alphabet-codes sure sure. I will take some other issue ❤️

AceTheCreator commented 4 years ago

@mrfambo cool 😎

sktguha commented 3 years ago

I think this issue should be closed, as its fixed by the above linked PR

bvaughn commented 3 years ago

Seems reasonable.

Prizrak55 commented 2 years ago

If anyone else is watching and looking for an explanation. The browser extension, which was not even close to development at all, blocked and this problem appeared