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

Uncaught ReferenceError: _this5 is not defined #969

Closed
timneutkens opened this issue May 9, 2018 · 10 comments · Fixed by #1002
Closed

Uncaught ReferenceError: _this5 is not defined #969

timneutkens opened this issue May 9, 2018 · 10 comments · Fixed by #1002

Comments

@timneutkens
Copy link

If you are reporting a bug or having an issue setting up React Hot Loader, please fill in below. For feature requests, feel free to remove this template entirely.

Description

After hot-reloading a file with multiple components (4 to 5) in one file an error is thrown

VM97:6 Uncaught ReferenceError: _this5 is not defined
    at value (eval at __reactstandin__regenerateByEval (header.js:996), <anonymous>:6:9)
    at HTMLUnknownElement.callCallback (react-dom.development.js:540)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:579)
    at Object.invokeGuardedCallback (react-dom.development.js:436)
    at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:450)
    at executeDispatch (react-dom.development.js:834)
    at executeDispatchesInOrder (react-dom.development.js:856)
    at executeDispatchesAndRelease (react-dom.development.js:954)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:965)
    at Array.forEach (<anonymous>)

Expected behavior

Hot reload should be applied and not crash the component

Actual behavior

What actually happens:

_this5 is not defined

@timneutkens
Copy link
Author

Sounds very similar to #928

@theKashey
Copy link
Collaborator

There was _this, this2, this3, half year later someone asked for this4, and now this5.
😩🤘

@timneutkens
Copy link
Author

I wonder if there's a better way to do this. cc @hzoo @loganfsmyth

@timneutkens
Copy link
Author

Specifically @theKashey has to keep adding this

if (hasRegenerate) {
target[REGENERATE_METHOD](
key,
`(function REACT_HOT_LOADER_SANDBOX () {
var _this = this; // common babel transpile
var _this2 = this; // common babel transpile
var _this3 = this; // common babel transpile
return ${injectedMembers[key]};
}).call(this)`,
)
} else {

@loganfsmyth
Copy link

I'm happy to try to help, but it would go a long way if someone could spell out what this wrapper is doing, since I'm not familiar with the internals of the hot loader.

What ends up running at the end, and why isn't _this5 already available in the outer scope?

Can could in theory generate any number of _this variables, dependent only on how many arrow functions and this references you have in a single file.

@theKashey
Copy link
Collaborator

theKashey commented May 9, 2018

So what we are doing - reading function body from one class, and executing it in the scope of another. as result all variables, possible visible from a function, including this, are right.

@loganfsmyth - this problem could be fixed with easy, if only you know babel. And look like - you know.

We just need to place our "regenerator" function inside a constructor, the place where all those thisN already defined. Currently, we are just adding it to the class.
The trick is - we have to the put a function into the transpiled class constructor, so in the scope, where this5 is already defined.
Link to sources - https://github.com/gaearon/react-hot-loader/blob/master/src/babel.dev.js#L176 - just appending class methods. Works, but not always :)

Moving regenerator into constructor will not cover some inheritance cases, as long they will have a "place" inside another constructor, but it will be better than current state.

@theKashey theKashey self-assigned this May 9, 2018
@loganfsmyth
Copy link

It seems like, along with the current behavior of injecting

 [REGENERATE_METHOD](key, code){
   this[key] = eval(code);
 }

You could special-case if the class has a constructor, also inject

 this[REGENERATE_METHOD] = function(key, code) {
   this[key] = eval(code);
 };

in the constructor? Then you could use that instead.

As you said, there are a lot of edge cases in approaches like this, but I feel like the logic in here is already a little scary to me, so it's not much worse with this :P

@theKashey
Copy link
Collaborator

Just to double check - adding code like

 [REGENERATE_METHOD] = (key, code) => this[key] = eval(code);

will result regenerator code to be moved inside a constructor?
What is the "right" way to put this method there?

@theKashey
Copy link
Collaborator

I have failed :(

To move renerate inside constructor and keep the "// @ts-ignore" comments.

The move itself is relatively easy, but how to add comments :(

@theKashey
Copy link
Collaborator

Just add this4-6 for now. Will help for a while.
If anybody could help modify babel plugin - please do it.

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

Successfully merging a pull request may close this issue.

3 participants