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 –
How to solve it?
There are two solutions for this –
- Bind the functions in constructor.
- 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> ); } }