Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Sinsstranger opened this issue Oct 28, 2020 · 27 comments
Closed

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

Sinsstranger opened this issue Oct 28, 2020 · 27 comments

Comments

@Sinsstranger
Copy link

Sinsstranger commented Oct 28, 2020

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?

@Sinsstranger Sinsstranger added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Oct 28, 2020
@bvaughn
Copy link
Contributor

bvaughn commented Oct 28, 2020

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.

// Connect renderers that have already injected themselves.
hook.renderers.forEach((renderer, id) => {
attachRenderer(id, renderer);
});

// Do the same for any already injected roots.
// This is useful if ReactDOM has already been initialized.
// https://github.com/facebook/react/issues/17626
hook.renderers.forEach((injected, id) => {

DevTools initializes the hook with a renderers map specifically for Fast Refresh:

Object.defineProperty(
target,
'__REACT_DEVTOOLS_GLOBAL_HOOK__',
({
// This property needs to be configurable for the test environment,
// else we won't be able to delete and recreate it beween tests.
configurable: __DEV__,
enumerable: false,
get() {
return hook;
},
}: Object),
);

Fast Refresh does the same if DevTools wasn't around to initialize the hook:

// For React Web, the global hook will be set up by the extension.
// This will also run before us.
let hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;
if (hook === undefined) {

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
Copy link
Author

Sinsstranger commented Oct 28, 2020

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
Copy link
Contributor

bvaughn commented Oct 28, 2020

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:

// For React Web, the global hook will be set up by the extension.
// This will also run before us.
let hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__;
if (hook === undefined) {
// However, if there is no DevTools extension, we'll need to set up the global hook ourselves.
// Note that in this case it's important that renderer code runs *after* this method call.
// Otherwise, the renderer will think that there is no global hook, and won't do the injection.
let nextID = 0;
globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {
renderers: new Map(),
supportsFiber: true,
inject(injected) {
return nextID++;
},
onScheduleFiberRoot(
id: number,
root: FiberRoot,
children: ReactNodeList,
) {},
onCommitFiberRoot(
id: number,
root: FiberRoot,
maybePriorityLevel: mixed,
didError: boolean,
) {},
onCommitFiberUnmount() {},
};
}

My guess was that something else (another extension?) was initializing the hook so that this Fast Refresh check didn't pass:

if (hook === undefined) {

But this line later throws:

hook.renderers.forEach((injected, id) => {

@gaearon gaearon changed the title Bug: Crash with "hook.renderers is undefined" Oct 28, 2020
@bvaughn
Copy link
Contributor

bvaughn commented Oct 28, 2020

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

@Sinsstranger
Copy link
Author

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

@gaearon
Copy link
Collaborator

gaearon commented Nov 1, 2020

@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
Copy link
Author

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
Copy link
Contributor

bvaughn commented Nov 2, 2020

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
Copy link
Collaborator

gaearon commented Nov 2, 2020

Do you use React with any third-party renderers?

@VoliBearCat
Copy link

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

@bvaughn
Copy link
Contributor

bvaughn commented Nov 3, 2020

@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
Copy link
Contributor

bvaughn commented Nov 3, 2020

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
Copy link
Contributor

bvaughn commented Nov 3, 2020

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

@gaearon
Copy link
Collaborator

gaearon commented Nov 3, 2020

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

@bvaughn bvaughn added good first issue and removed Resolution: Needs More Information Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels Nov 3, 2020
@VoliBearCat
Copy link

@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
Copy link
Contributor

bvaughn commented Nov 3, 2020

Makes sense. Hope you like the new DevTools! 😄

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
Copy link
Contributor

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

@bvaughn
Copy link
Contributor

bvaughn commented Nov 4, 2020

@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.

@bvaughn bvaughn changed the title Crash with "hook.renderers is undefined" Fast Refresh: Improve dev experience when DevTools hook is disabled Nov 4, 2020
@mrfambo
Copy link

mrfambo commented Nov 6, 2020

@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
Copy link

mrfambo commented Nov 6, 2020

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
Copy link
Contributor

bvaughn commented Nov 6, 2020

Test case would be nice.

@AceTheCreator
Copy link
Contributor

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

@mrfambo
Copy link

mrfambo commented Nov 6, 2020

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

@AceTheCreator
Copy link
Contributor

@mrfambo cool 😎

bbeckercscc added a commit to bbeckercscc/react that referenced this issue Nov 7, 2020
…ble handling of dev tools global hook being disabled
@sktguha
Copy link
Contributor

sktguha commented Nov 12, 2020

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

@bvaughn
Copy link
Contributor

bvaughn commented Nov 12, 2020

Seems reasonable.

@bvaughn bvaughn closed this as completed Nov 12, 2020
@ghost ghost mentioned this issue Jun 9, 2021
@Prizrak55
Copy link

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

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

No branches or pull requests

8 participants