Arrow functions, context and why they're so important in React.js
An unintuitive concept, but these are fundamentally different
<button onClick={this.runFunction}//>
//NOT THE SAME
<button onClick={() => this.runFunction()}//>
Try it out yourself later in a component, where
this.runFunction
uses this.setState
. The first will
throw an error. The other will not. Theres a short explanation and a long one.
To someone who has no idea why these two are different, I think a long explanation
is in order.
function
and its this
play by its own rules
The defintion of context in a function
does not obey lexical
scoping unless you tell it to. If you give it no declarations, it assumes
this
is the window object.
Strict declaration of context
this.myFunction // 'this' is my context, where my 'this' resulting declaration will obey lexical scoping
function ConstructorExample() {
this.testAnonThis = function() { //this.testThis binds this function to my constructor's context
let anonThis = (function(){
return this
})() //anonymous function. THIS HAS NO BINDING. Remember, not lexically scoped.
console.log(`anonThis is the window object?: ${window === anonThis}`)
}
}
new ConstructorExample().testAnonThis()
//anonThis is the window object?: true
Why do function
-based anonymous functions have this === window
?
JavaScript assigns context very late. As mentioned before, the assignment of this in an anonymous function does not obey lexical scoping. Some see it as a strength, because you can reuse functions and keep things lean, while others call it unintuitive and flawed by design.
Arrow functions have no this
So important to understand, that it hurts. I need to explicitly state it:
functions assigned usingfunction
have a context automatically asigned: (this
). Arrow function do not have athis
So how does this apply to React.js?
10 years later, I'm going to explain that original statement.
<button onClick={this.runFunction}/>
This is assigned using function
, which has its own context.
<button onClick={()=> this.runFunction()}/>
Assigned as an arrow function, which has a this
that is
inherited from the React component class.
My personal opinion: Just use arrow functions, all the time.
It's important to understand fundamentals. But at the end of the day, the ECMAScript team introduced arrow functions for a very good reason: They make so much sense.
In fact, they make sense to the point where you don't even have to know what's going on to use them flawlessly. In my opinion: an incredible strength, but a minor detriment. The future will consist of developers that don't understand fundamentals, such as myself, from 3 months ago. But you will never run into context issues if your event handlers are arrow functions.
Yes, I know I didn't explain how to fix the function
-based assignment
Brainless answer: use bind.
<button onClick={this.runFunction.bind(this)}/> //proper scope
If I somehow not been talking to myself for the past 7 blog posts and any viewers want to understand this topic, feel free to leave me a comment and I'll go over bind, call, and apply.
Comments
Post a Comment