When I’m teaching React to developers, one thing that comes up often is dealing with a common error. But here’s the interesting thing: it’s not running into the error that comes up all the time, it's how to deal with it that surprises them. I’ve always wanted to have something to point to that the scenario & why one option is better than others, even though there are plenty of ways to address the issue. That’s what this post is!
Let me start that I’m not the first person to write about this. Spend a few minutes exercising your Google-Fu and you’ll find plenty of others have written about the same thing.
If you’ve worked with React, you’ve probably written a component like this:
In this very simple component, you are accessing a member from the class from the event handler. You think this
is pointing to the Sample
class, but what you get is a nasty error. TypeError: Cannot read property ‘foo’ of undefined
Why? What the this
keyword is bound to depend on where it is defined. In this case, this
reverts to its default binding. In the case where you are running in non-strict mode, this is the global window object, but in the case of strict mode, this is undefined
.
So how do you get around this? You have two options, one of which has two flavors.
This is the easiest to understand, but it also isn’t the best option. In this option you explicitly bind the this
value to the thing you want it to refer to in a function:
Now, by just adding that single line in the constructor of your component, this will refer to the component within your event handler function.
While this approach works, there are two issues with it:
Arrow functions don’t have to worry about this. This is because when you use an arrow function, the event handler is automatically bound to the component instance so you don’t need to bind it in the constructor.
When you use an arrow function you are binding this
lexically. According to the definition taken from Stack Overflow, lexically “means that a variable defined outside a function can be accessible inside another function defined after the variable declaration”.
There are two ways you can do this. I prefer to use the public class fields syntax. In this scenario, I like to think that I’ve assigned code to a variable and I’m using the variable in the handler reference. Notice how the declaration of the handler is written. An arrow function is used to assign the code to a variable that’s called as the handler.
The other way is by including the arrow function in the callback. Here, you move the arrow function syntax from the previous snippet from the definition to where it’s used:
Whichever way you prefer, I’d pick at least one of the latter two options for your components.