Fix cannot read property setState of undefined in React.js

avatar

Borislav Hadzhiev

Wed Oct 20 20212 min read

banner

Photo by Lê Tân

Fix cannot read property 'setState' of undefined #

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.

typeerror cannot read property setstate of undefined

Here is an example of how the error occurs.

App.js
import React, {Component} from 'react'; class App extends Component { constructor(props) { super(props); this.state = { isActive: false, }; } toggleIsActive() { // ⛔️ `this` is undefined 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;

Notice that we defined the toggleIsActive method, but we haven't bound the context of the this keyword.

Therefore, the 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.

index.js
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 classes' constructor.

App.js
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.

index.js
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.
Use the search field on my Home Page to filter through my more than 1,000 articles.