When writing a React class component, you may encounter an error saying this.setState
is not a function as shown below:
TypeError: this.setState is not a function
This error happens when JavaScript can’t find the setState()
function from the context of this
keyword. There are two ways to fix this error:
- Declare the class method using the arrow function syntax
- Bind the class method reference during constructor call or inside the calling property
This tutorial will show you how to use both ways to fix your error.
You may have a React class component similar to the following code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
handleClick() {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
The Example
component above will execute the handleClick()
function each time the user clicks on the button that the component renders.
But when you try to run the component above, you will get the this.setState is not a function
error:
This is because the this
keyword inside the handleClick()
function refers to the function itself instead of the class where the function belongs.
Fixing this.setState error with arrow function syntax
To avoid the this
keyword context from being replaced by the function, you can declare the function using JavaScript arrow function syntax that was introduced in JavaScript ES6 version.
Let’s change the handleClick()
function declaration as follows:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
handleClick = () => {
this.setState({ count: this.state.count + 1 })
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
And just like that, the error should be fixed.
Fixing this.setState error with binding class methods
Although using the arrow function syntax is the recommended way to declare class methods, you can also fix the error by binding this
keyword to your methods during the constructor call.
For example, the following code binds this.handleClick
function referenced inside the button’s onClick
property during the constructor call:
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleClick = this.handleClick.bind(this);
}
But the downside of this way is that you need to bind each function that needs to use this.setState()
function in the constructor.
If you have three different methods that call the setState()
method in one class, then you need to bind each of them:
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleClick() {
// call setState
}
handleChange() {
// call setState
}
handleSubmit() {
// call setState
}
An alternative way to bind in the constructor is to bind in each function reference. In the example, you can bind to the onClick
property of the <button>
element as follows:
<button onClick={this.handleClick.bind(this)}>
When you fix the error this way, you need to use the bind
method in the constructor or in the event handler property like onClick
.
Conclusion
I’d recommend you to change your class method declaration to use arrow syntax over binding each method reference whenever you can.
Then again, you may want to consider using a function instead of a class for declaring a React component. Since the release of React hooks in 2018, function component syntax is the recommended way to create React components.