Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
71
rated 0 times [  74] [ 3]  / answers: 1 / hits: 22322  / 7 Years ago, wed, december 6, 2017, 12:00:00

I know about the general theory of this binding (function call site what matters, implicit, explicit binding, etc...) and the methods to solving the problem of this binding in React so it always points to what I want this to be (binding in constructor, arrow functions, etc), but I am struggling to get the inner mechanisms.



Take a look at these two pieces of code:



class demo extends React.component {
goToStore(event) {
console.log(this)
}

render() {
<button onClick={(e) => this.goToStore(e)}>test</button>
}
}


vs.



class demo extends React.component {
goToStore(event) {
console.log(this)
}

render() {
<button onClick={this.goToStore}>test</button>
}
}


What I know is that:




  • in both versions we end up successfully in the goToStore method, because the this inside the render() method is automatically bound (by React) to the component instance

  • the first one succeeds because of that,

  • the second one fails, because class methods in es6 are not bound to the component instance, thus resolving this in the method to undefined



In theory in the first version as far as I understand, the following occurs:




  1. the button click handler is an anonymous arrow function, so whenever I reference this inside of it, it picks up this from the environment (in this case from render())

  2. then it calls the goToStore method, that is a regular function.

  3. because the call seems to fit the rules of implicit binding (object.function()) object will be the context object and in such function calls it will be used as this

  4. so, inside the goToStore method the lexically picked up this (used as a context object) will resolve to the component instance correctly



I feel 3. and 4. is not the case here, because then it would apply to the 2. case:



<button onClick={this.goToStore}>test</button>


Also with this the context object.



What is happening exactly in this particular case, step-by-step?


More From » reactjs

 Answers
41

As the MDN docs states




An arrow function does not have its own this; the this value of the
enclosing execution context is used




So you would think of



onClick={(e) => this.goToStore(e)}


as being an anonymous function which can be written as



    (e) => { 
return this.goToStore(e)
}


Now here in this anonymous function this refers to the lexical context of the render function which in turn refers to the React Class instance.



Now



Context is most often determined by how a function is invoked. When a function is called as a method of an object, this is set to the object the method is called on:



var obj = {
foo: function() {
return this;
}
};

obj.foo() === obj; // true


The same principle applies when invoking a function with the new operator to create an instance of an object. When invoked in this manner, the value of this within the scope of the function will be set to the newly created instance:



function foo() {
alert(this);
}

foo() // window
new foo() // foo


When called as an unbound function, this will default to the global context or window object in the browser.



So here since the function is called like this.goToStore() this inside it will refer to the context of React component.



However when you write onClick={this.goToStore}, the function is not executed but a reference of it is assigned to the onClick function, which then later invokes it, causing this to be undefined inside the function as the function runs on the context of the window object.



Now even though onClick={(e) => this.goToStore(e)} works, whenever render is called a new function instance is created. In your case its easy to avoid, just by created the function goToStore using arrow function syntax.



goToStore = (e) => {

}


Check the docs for more details on this


[#55740] Monday, December 4, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
cristopherh

Total Points: 402
Total Questions: 117
Total Answers: 84

Location: Monaco
Member since Fri, Sep 24, 2021
3 Years ago
;