I wanted to understand the basic difference between how the below syntax works.
// Syntax 1
class Component extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
// ...
}
}
// Syntax 2
handleClick = () => {
console.log('this is:', this)
}
<button onClick={this.handleClick}>
{'Click me'}
</button>
While syntax 1 needs an explicit binding to be specified inside constructor. However, it seems like with syntax 2, that is not needed. How is syntax 2 able to achieve the binding automatically ?
I assume this understanding/syntax can be extended for any framework including React, Angular, Ember, etc
Class fields - that is, properties defined directly inside the class body - are essentially just syntax sugar for the same thing inside the constructor. So, this:
class Something {
handleClick = () => {
console.log('this is:', this)
}
}
is, desugared:
class Something {
constructor() {
this.handleClick = () => {
console.log('this is:', this)
};
}
}
With the sugaring removed, it should be clear what's going on - the arrow function means that the this refers to what this is in the constructor, which is the instance itself, no binding needed.
This isn't just a React or framework thing - these are standard rules in vanilla JavaScript.
If you don't bind the method or use an arrow function or anything like that, then:
<button onClick={this.handleClick}>
fails for the same reason that
someButton.addEventListener('click', myObj.someFn)
will also fail to call someFn with a calling context of myObj - all the browser knows is to call the callback passed to the click listener; the calling context of myObj gets lost when passed like that.
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