why this is not defined in function increaseCounter but is defined in getBadgeClass function ?
<button onClick = { this.increaseCounter } className = {
this.getBadgeClasses() }>increment</button>
getBadgeClasses() {
let classes = "badge m-2 badge-";
classes += this.state.count === 0 ? "warning" : "primary";
return classes;
}
increaseCounter(){
this.state.count++;
}
why this is not defined in function increaseCounter but is defined in getBadgeClass function ?
<button onClick = { this.increaseCounter } className = {
this.getBadgeClasses() }>increment</button>
getBadgeClasses() {
let classes = "badge m-2 badge-";
classes += this.state.count === 0 ? "warning" : "primary";
return classes;
}
increaseCounter(){
this.state.count++;
}
Share
Improve this question
asked Apr 1, 2019 at 3:58
Sunil TripathiSunil Tripathi
6161 gold badge7 silver badges12 bronze badges
3
-
2
Calling context is different. Try
onClick={()=>this.increaseCounter()}
oronClick={ this.increaseCounter.bind(this)}
– charlietfl Commented Apr 1, 2019 at 4:01 - 2 Possible duplicate of How to access the correct `this` inside a callback? – VLAZ Commented Apr 1, 2019 at 4:02
-
And don't assign to state like
this.state.count++;
instead usethis.setState(prevState => ({count:prevState.count + 1}));
– ivica.moke Commented Apr 1, 2019 at 7:49
5 Answers
Reset to default 6You should bind function which uses this
. To save this
context you can use one of these ways:
1) Bind functions in the constructor:
constructor(props) {
super(props);
this.getBadgeClasses = this.getBadgeClasses.bind(this);
this.increaseCounter = this.increaseCounter.bind(this);
}
2) Or you can use arrow function. It saves this
context as well:
increaseCounter = () => {
...your code
}
You can read more here: https://medium./silesis/handle-events-in-react-with-arrow-functions-ede88184bbb#4803
When the interpreter reaches the ponent, this.getBadgeClasses() executes right away. It is called on the object referred by this so the keyword this inside the function, points to the same object. So it is able to resolve the reference to the state.
On the other hand, this.increaseCounter() does not execute right away. The attribute onClick just stores a reference to that function. Whenever a user clicks on the button, that referenced function is called on the global object. So the keyword this is set to undefined in the strict mode. To resolve this, you have to bind the increaseCounter() to this in the constructor.
you have to bind this
to increaseCounter
function to access this
object. Do this :
<button onClick = { this.increaseCounter.bind(this) }
className = { this.getBadgeClasses.bind(this) }
>
increment
</button>
In addition to what Shahrukh has mentioned, in strict mode global object refers to undefined in place of the window object. So when the function increaseCounter() is called on global object, it calls on an undefined object.
Also, when a function is used as an event handler, its 'this' is set to the element the event fired from. As a DOM event handler. Therefore, increaseCounter()'s this is set to global context.
Since in JavaScript class methods are not bound by default unless you specifically bind them, they are just "function objects". Any object or variable can reference the function because it's just a pointer, like any other object.
The question asked is actually to be blamed on JavaScript, not React.js.
There are two parts to this error. The first is that the error handler must be defined like this, in order to make this
work correctly with the error function:
increaseCounter = () => { ... }
The second part of the problem is that you can't change the state directly; instead, you must change the state using this.setState()
:
increaseCounter = () => {
this.setState(prevState => {
return {count: prevState.count + 1}
}
}