To understand my love affair with arrow functions, we need to think about a common error that arises when coding a React app. Let’s say we have a simple Search Bar component in our app and as we are building it out, we would like to test our form submission by console logging whatever the input is. Now, an old school way of handling this might look like the following:
Our function for console logging our input (and later for handling whatever we want to do with that input once the form is submitted) is on line 10:
Standard looking function, great. But when we run this program, we get an error.
To understand this better, I played around with some code. Let’s say I define a class called ‘Pet’ and I want to make sure that whatever instance of that class I create can produce a sound that I define.
Great, that’s easy. Now let’s look at this:
In this case, I created an object ‘cat’ that was outside of my ‘Pet’ class, but I gave it the ‘speak’ function that I defined for that class. Or, rather, I gave it a reference to the ‘speak’ function that I defined in my ‘Pet’ class, which I set to be called on whatever ‘this’ would be. By doing this, it was almost as if I were redefining the ‘speak’ function in the ‘Pet’ class to return ‘cat.sound’.
If we generalize, essentially what we are telling our code is: “look to the left of the dot and THAT is what you call the method on; in other words, whatever is to the left of the dot is now to be considered this”.
However, if we generalize even more and assign the function reference to a variable and then try to call that variable, we get:
If we think back to what we said above, that the code must look to the left of the dot to understand what ‘this’ is referring to…we have NOTHING. So the code has no idea what to call the method ‘speak’ on.
This was some generic code that I played around with. What does this mean for a React app that you are asked to work on as a developer? Well, the ‘cannot read property X of undefined’ error is probably one of the most common you will come across as a professional developer. Even people who have worked with React for many years still encounter it. Importantly, because React is so versatile and allows for multiple solutions to the same problem, this issue often arises because different developers approach classes and functions slightly differently. This means that as a professional developer, you will have to be comfortable dealing with legacy code written in a way that would not have been your preferred way.
Anyway, getting back to our error…just like in the example code we played with, React does not understand what ‘this’ is referring to when we try to console log this.state.term.
What does any of this have to do with how much I love arrow functions? We’re getting there. As we mentioned, React is super flexible…so there are a number of ways of dealing with this, though there are really 3 main ways.
1. Using .bind
One way to address this issue is to use .bind. In order to do this, you need to define a constructor method, like so:
Within the constructor method, you bind the speak method to a ‘this’ value, which will be an instance of the ‘Pet’ class; in other words, you essentially create a new version of the function with the correct value of ‘this’ fixed.
2. Using Arrow Functions
Ok, here is where we get to my love affair with arrow functions. ES6 ushered in a new way of dealing with the messiness of ‘this’ when it introduced arrow functions because ARROW FUNCTIONS AUTOMATICALLY BIND THE VALUE OF ‘THIS’ FOR THE CODE WITHIN THE FUNCTION.
That’s it, no messing with a constructor function or explicitly binding anything or essentially having to write a modified version of a function. Just by using the arrow function, React knows that anytime it sees ‘this’ , it refers to an instance of whatever class that function was defined within. And now if we run the code, no more error message:
3. Using an arrow function as a callback
The final way to fix this STILL involves arrow functions (woohoo!). In this case, the function can still be defined arrow-less but then passed as a callback function into the JSX. That callback function will be…an ARROW FUNCTION. In this case, we need to invoke the function and pass in the event because onSubmit will only call the arrow function once, when the form is submitted. While this solution requires more code than a simple arrow function definition, it still can be useful depending on what the codebase looks like.
Any of these three methods is TOTALLY valid…but, well, for me it’s all about those arrows. Thank you, ES6.