Last updated: Apr 6, 2024
Reading time·2 min

The "Cannot read property 'setState' of undefined" error occurs when a class
method is called without having the correct context bound to the this
keyword.
To solve the error, define the class method as an arrow function or use the
bind method in the classes' constructor method.

Uncaught TypeError: Cannot read properties of undefined (reading 'setState')
Here is an example of how the error occurs.
import React, {Component} from 'react'; class App extends Component { constructor(props) { super(props); this.state = { isActive: false, }; } toggleIsActive() { // ⛔️ `this` is undefined here // Uncaught TypeError: Cannot read properties of undefined (reading 'setState') this.setState({isActive: !this.state.isActive}); } render() { console.log(this.state.isActive); return ( <div> <button onClick={this.toggleIsActive}>Toggle</button> </div> ); } } export default App;
Notice that we defined the toggleIsActive method, but we haven't bound the
context of the this keyword.
this keyword in the toggleIsActive method has a value of undefined.To solve the error, switch the toggleIsActive method to use an arrow function
instead.
import React, {Component} from 'react'; class App extends Component { constructor(props) { super(props); this.state = { isActive: false, }; } // ✅ Works because we used an arrow function // to declare the method toggleIsActive = () => { this.setState({isActive: !this.state.isActive}); }; render() { console.log(this.state.isActive); return ( <div> <button onClick={this.toggleIsActive}>Toggle</button> </div> ); } } export default App;

This works because arrow functions use the this keyword of the enclosing
scope - in our example, the enclosing scope is the specific component instance.
Alternatively, you can call the Function.bind() method in the class's constructor.
import React, {Component} from 'react'; class App extends Component { constructor(props) { super(props); this.state = { isActive: false, }; // ✅ Bind method here this.toggleIsActive = this.toggleIsActive.bind(this); } // ✅ Works toggleIsActive() { // ✅ `this` is correctly bound here this.setState({isActive: !this.state.isActive}); } render() { console.log(this.state.isActive); return ( <div> <button onClick={this.toggleIsActive}>Toggle</button> </div> ); } } export default App;

The bind method creates and returns a new function where the this keyword is
set to the provided value.
The this keyword in the constructor refers to the class instance.
This is the case when working in classes in vanilla JavaScript as well.
class Person { constructor(first, last) { this.first = first; this.last = last; console.log(this); // 👉️ {first: 'James', last: 'Doe'} } } const p1 = new Person('James', 'Doe');
This enables us to bind the method in the constructor and use the bound
version throughout the class.
My preferred approach is to use arrow functions to define my class methods when
possible. This way I don't have to think about the this keyword and everything
just works by default.