React - How to fix this.setState is not a function error

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.

Take your skills to the next level ⚡️

I'm sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.