I'm trying to understand the behavior of the this keyword in a react component ( Arrow function vs Regular function) when paired with a event handler.
For this, I created two examples, one with HTML/vanilla JS, the other one with React.
HTML/VanillaJS
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn-arr">Log this Arr</button>
<button class="btn-reg">Log this Reg</button>
<script>
class App {
logThisArr = () => {
console.log('Arr : ', this);
};
logThisReg = function () {
console.log('Reg : ', this);
};
}
const app = new App();
const btnArr = document.querySelector('.btn-arr');
const btnReg = document.querySelector('.btn-reg');
btnArr.addEventListener('click', app.logThisArr); // Arr : App {logThisArr: ƒ, logThisReg: ƒ}
btnReg.addEventListener('click', app.logThisReg); // Reg : <button class="btn-reg">Log this Reg</button>
</script>
</body>
</html>
React
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
class App extends Component {
logThisArr = () => {
console.log('arrow : ', this);
};
logThisReg = function() {
console.log('Reg : ', this);
};
render() {
return (
<div className="App">
<button onClick={this.logThisArr}>Log this Arr</button>
{/* Arr : App {props: {…}, context: {…}, refs: {…}, updater: {…}, logThisArr: ƒ, …}*/}
<button onClick={this.logThisReg}>Log this Reg</button>
{/*Reg : undefined */}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
Why don't I get the same output when using a regular function ? In react I get "undefined" and in vanillaJS I get the button object.
Thank you !
Alright, so, thank you both.
I think I understand a bit better after a lot of reading.
It goes way deeper than the original post. We first need to understand the difference between "execution context" and "lexical scope". http://ryanmorr.com/understanding-scope-and-context-in-javascript/
Then we can start looking at the behavior of "this" in regular and arrow functions.
Inside regular fonctions :
Inside arrow functions :
That's why in react the use of arrow functions or the use of ".bind()" is necessary, because we cannot rely on regular fonctions ( in which the "this" keeps changing) to access the attributes of our instantiated object of App class.
In our specific case, as of why do I get "undefined" when using the regular fonction in the react code, TBT I'm not exactly sure (maybe because of react internal shenanigans) but I can guess it's because of two things :
Anyways, this is not exhaustive, and I havent understood everything yet, but I now understand a bit better why we need to bind/use arrow fonctions in React and how they work.
These really helped me get to the bottom of things :
And also the link mentionned by @brian Thomoson : How to access the correct `this` inside a callback?
Thank you guys.
Regards,