Reputation: 579
Please point me to my error.
I want to write an interactive button that displays the number of clicks on it. With each next click, the number on the button have to increase by one. Initial number is 0, so, for example, after 5 clicks it becomes 5. Without an interactive element, the code is rendered normally.
Here is my code:
class Button extends React.Component{
constructor(props){
super(props);
this.state = {counter: 0};
};
handleClick(){
this.setState(
prevState => ({counter: prevState.counter + 1})
);
}
render(){
return (
<button onClick={this.handleClick}>{this.state.counter}</button>
);
}
}
Here is the error I get:
TypeError: Cannot read property 'setState' of undefined
handleClick
src/index.js:30:6
27 |
28 | render(){
29 | return (
> 30 | <button onClick={this.handleClick}>{this.state.counter}</button>
| ^ 31 | );
32 | }
33 | }
View compiled
▶ 20 stack frames were collapsed.
Thank you in advance!
Upvotes: 3
Views: 1343
Reputation: 31683
You could go a little bit more advanced and use the ECMAScript 6 arrow function syntax, which will avoid that kind of problem and also avoid the need to use .bind(this)
.
If you declare handleClick
like handleClick = () => {}
, you wont need to use in your constructor this.handleClick.bind(this)
. Everything will work normally when you use this
, it will be the class's this
, not the function's this
.
This is using newer versions of javascript and is highly recommended to don't use .bind(this)
which can cause some issues.
Just declare handleClick
like this and it will work without the need to use .bind(this)
handleClick = () => {
this.setState(
prevState => ({counter: prevState.counter + 1})
);
}
Upvotes: 2
Reputation: 407
I think you have two options:
this.handleClick.bind(this)
, which will ensure that your this
actually refers to the button object.Use newer format, which I like better.
handleClick = () => {
this.setState(
prevState => ({counter: prevState.counter + 1})
);
}
A little more helpful documentation on a lot of React topics here: https://reactjs.org/docs/react-component.html
Upvotes: 1
Reputation: 1807
You have to bind the click handler:
...
constructor(props){
super(props);
this.state = {counter: 0};
this.handleClick.bind(this) // <----- here
}
...
Upvotes: 1
Reputation: 1927
In your example, this
in your handleClick()
function refers to the scope of the event that was fired from your click. In order to solve this you must bind the functions scope to the element.
Add this.handleClick = this.handleClick.bind(this)
to your constructor and it should work fine.
https://reactjs.org/docs/handling-events.html
Upvotes: 4