While learning JS and React I've come across confusing differences in tutorials.
I'll split the questions below with examples. I understand bind for regular functions and this context, it's just arrow functions and how I've seen them used/declared that's confusing.
Please don't just refer to duplicates as I've found conflicting answers in tutorials which have confused me, so looking for the source of truth to understand in a simple way. Answers related to the questions and examples below would help better.
1 - I've seen examples where a tutorial says the value of 'this' would be window as the arrow function inherits from the global/window scope but I've also seen tutorials where they say it will inherit this from the class context - which is correct? if you could please explain.
class MyClass {
value = 'Hello World!'
clickHandler = () => { console.log(this.value) };
}
2 - I have 2 parts to this question - i - Why is the syntax clickHandler = () => rather than clickHandler () =>
I ask this because I read class methods can be defined with 'functionName () {}' so why do arrow functions treat the method name as a variable?
ii - What is the value of this in the below code? same as question 1 I guess, does this refer to the window object or the class?
class Foo extends React.Component {
constructor() {
}
clickhandler = () => {
console.log("you clicked me!!")
}
render() {
return(
<div>
<button onClick={this.clickhandler}> // => CALLBACK
3 - Here I see the event handler is an inline function, but it looks like it gets invoked because of the () at the end, sometimes as in the follow on snippet, you can see that just the function name is given without the parentheses, shouldn't they be there also?
class MyComponent extends React.Component {
showValue() {
console.log(this.props.value);
}
render() {
return (
<button onClick={() => this.showValue()}>Do Something</button>
);
}
}
-------------------------------------------
showValue() {
console.log(this.props.value);
}
render() {
return (
<button onClick={this.showValue}>Do Something</button>
);
}
Why is the syntax clickHandler = () => rather than clickHandler () =>
foo () => ...
syntax isn't valid for ES6 classes and this concept wouldn't make sense. foo() {...}
is syntactic sugar for prototype method:
function Class() {}
Class.prototype.foo = function () {
// this instanceof Class === true
}
This wouldn't work if Class.prototype.foo
were an arrow; this
would be retrieved from the scope where Class
is defined:
// this === undefined
Class.prototype.foo = () => {
// this === undefined
}
foo = () => ...
is class field syntax, which is stage 3 proposal and not a part of ES6.
class Class {
foo = () => {
// this instanceof Class === true
}
}
is syntactic sugar for:
class Class {
constructor() {
// this instanceof Class === true
this.foo = () => {
// this instanceof Class === true
}
}
}
I've seen examples where a tutorial says the value of this would be window as the arrow function inherits from the global/window scope but I've also seen tutorials where they say it will inherit this from the class context/scope - which is correct?
Arrow function gets lexical this
from enclosing scope. In case an arrow is defined in global scope, this
is window
, and undefined
in ES module scope.
In the example above an arrow is defined in class constructor scope, this
is class instance.
Here I see the event handler is an inline function, but it looks like it gets invoked because of the () at the end, sometimes as in the follow on snippet, you can see that just the function name is given without the parentheses, shouldn't they be there also?
Callback function is expected to be passed as onClick
prop. this.showValue()
calls a function and returns a value from it. Unless a value is a function, too, invoking a method in-place like onClick={this.showValue()}
is incorrect.
onClick={this.showValue}
passes class method as a callback. Since showValue
is prototype method that isn't bound to proper this
context, a callback will be executed with wrong context (the problem is explained in this question), while onClick={() => this.showValue()}
passes wrapper function as a callback that executes showValue
with correct context.
1- this
refers to current scope. In MyClass
this refers to class instance.
So the answer is both correct. In global scope this refers to the window, inside myclass
this refers to the class.
2- As you may notice in arrow function there's no need to bind functions with the class, so there syntax is different.
3- onClick={() => this.showValue()}>Do Something</button>
: creates a function each time click fires an event. It is useful when in some cases you want to pass extra args from component render to event handler.
onClick={() => this.showValue(event, id, name)}>Do Something</button>
but with onClick={this.showValue}>Do Something</button>
which is the usual case, you call the handler when it fires an event without creating new function each time.
But how it can identifies the handler? By binding, this
can recognize what is inside your scope because you are calling it inside which is showValue
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With