This question already has an answer here:
class App extends Component {
constructor(props) {
...
}
onChange = (e) => this.setState({term: e.target.value})
onSubmit(e){
e.preventDefault();
const api_key = "C1hha1quJAQZf2JUlK";
const url = `http://api.giphy.com/v1/gifs/search?q=${this.state.term}&api_key=${api_key}`;
}
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input value={this.state.term} onChange={this.onChange}/>
<button>Search!</button>
</form>
</div>
);
}
}
What is the difference between the two type of functions declared in the class (onChange and onSubmit). I get an error on referencing this.sate in const url if I declare it as an ES6 class method but changing it to arrow function fixes it.
I want to know how exactly 'this' is handled in both the cases
Also, how do I do it the other way? Say, if I want to use the same onSubmit function (ES6 class method) but want to handle this when I call it (in the form element), how do I do it ?
Using this.onSubmit.bind(this) ?
Arrow Functions lexically bind their context so this actually refers to the originating context.
In ES3/4 functions declaration you can use
this
by storing in some other variable.You need to use
bind
in your class's constructor with the ES6 class method. In essence, arrow functions do this for you automatically.The more important thing to note here is that I believe the arrow function here will be created on each instance of the class, where the ES6 class method will be made part of the class's prototype and shared amongst all instances.
Yes you must bind the method to the component in the constructor. It's because the arrow functions get automatically binded to the class therefore the scope of this is set in the method. While
onSubmit
is a regular function that is not yet binded therefore the this inside the method will reference the function and not the component.It's important to know that this syntax:
is just syntactic sugar for creating an instance method in the class constructor:
Note: This syntax is not an official part of the JavaScript language yet (currently in stage 3) so you must use a transpiler like Babel to handle it.
The value of
this
withinmethod
is the classA
because that is whatthis
points to in the constructor (since arrow functions inherit the context from the scope they are defined in):Defining a regular (non-arrow function) method on the class creates a method on the class prototype (not instance) but sets no rules on what
this
will be (sincethis
is dynamic in JS and depends on how a function is called, not how it's defined).If methods defined in either of these ways are called on the class instance (via the
.
), as per the rule of howthis
is bound when a function is called as a method of an object,this
will point to the class instance in both cases:One major difference between the two method declarations above is that the instance method has
this
always fixed to the class instance while the class (prototype) method does not (we can change it by using Function.prototype.apply or Function.prototype.call)A common occurrence where the
this
changes is within an event handler, where the event handler calls the function passed into it and binds the context to the element on which the event happened (so overrides the value ofthis
to be the element that was clicked or whatever the event was)This happens in React as well for all (synthetic) DOM event handlers.
Therefore, if we want our method's context to always point to the instance of the React component, we can use the instance method.
Another way of restricting the context but not using the special instance method syntax that requires Babel is to directly create an instance method ourselves by creating a new function from the class (prototype) method with a bound context (using Function.prototype.bind):
This allows us get arrive to the same result as using the special instance method syntax but with the currently available tools (ES2017 and under).
If for some reason we want a method that is always bound to something that is not an instance of the class, we can do that as well:
The key difference is that in ES5 we don't have auto binding which means you have to bind your event handler function manually in order to play with state or props inside the function in react. But in ES6 it does auto binding. That's the key difference
ES5: you have to bind onSubmit preferably in constructor
ES6:
The below is valid because it does auto binding.