React Error – cannot read property ‘setstate’ or ‘state’ or ‘props’ of undefined

Total
0
Shares

So, you got the React error – cannot read property ‘setstate’ or ‘state’ or ‘props’ of undefined? Alright. Let’s see why it happens and how to solve it.

We use setState() on this as this.setState(). So, setState is the property of this. The error says that React cannot read property ‘setstate’ of undefined, which means it is treating this as undefined.

In the same way, state and props are also the properties of this. We use them like this.state.foo or this.props.bar.

Why it happens?

It happens because the methods inside a class doesn’t bind themselves within the context and we need to do it in constructor. So, this below code will create error –

import React from "react";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      flag: 1
    };
  }

  onToggle(event) {
    this.setState((prevState) => ({
      flag: prevState.flag === 1 ? 0 : 1
    }));
  }

  render() {
    return (
      <div className="App">
        <p>Current Flag - {this.state.flag}</p>
        <p>
          <button onClick={this.onToggle}>Toggle Flag</button>
        </p>
        <p>
          <em>
            Button click will create{" "}
            <b>React Error - cannot read property 'setstate' of undefined</b>
          </em>
        </p>
      </div>
    );
  }
}

Check in live demo –

Open Live Demo

How to solve it?

There are two solutions for this –

  1. Bind the functions in constructor.
  2. Use ES6 arrow notation to declare functions.

To bind the function, use this code –

constructor(props){
  this.onToggle = this.onToggle.bind(this);
}

To use ES6 arrow notation, use this code –

onToggle = (event) => {
  // function body
}

Let’s check both of these in this code example –

import React from "react";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      flag: 1
    };
    this.onToggle = this.onToggle.bind(this);
  }

  onToggle(event) {
    this.setState((prevState) => ({
      flag: prevState.flag === 1 ? 0 : 1
    }));
  }

  onToggle2 = (event) => {
    this.setState((prevState) => ({
      flag: prevState.flag === 1 ? 0 : 1
    }));
  };

  render() {
    return (
      <div className="App">
        <p>Current Flag - {this.state.flag}</p>
        <p>
          <button onClick={this.onToggle}>
            Toggle Flag (Method bind in constructor)
          </button>
        </p>
        <p>
          <button onClick={this.onToggle2}>
            Toggle Flag (Method using ES6 arrow notation)
          </button>
        </p>
      </div>
    );
  }
}

    Tweet this to help others

Live Demo

Open Live Demo