[Solved] TypeError: Cannot read property ‘state’ of undefined in ReactJS

The issue Cannot read the property of undefined is quite common in JavaScript. When the variable is not defined, JavaScript can not read the undefined variable or property. A similar issue we can find in React JS. We analyze the issue and try to find a solution.

TypeError: Cannot read property 'state' of undefined
TypeError: Cannot read property ‘state’ of undefined
import React from 'react';
import * as courseActions from '../Redux/actions/courseAction';
import propTypes from 'prop-types';
import { connect } from 'react-redux';
class CoursePage extends React.Component {
  state = {
    course: {
      title: '',
    },
  };

  handlechange  (event) {
    const course = { ...this.state.course, title: event.target.value };
    this.setState({ course });
  };

  handleSubmit(event) {
    event.preventDefault();
    this.props.dispatch(courseActions.createCourse(this.state.course));
  };
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <h2>courses</h2>
        <h3>Add course</h3>
        <input
          type='text'
          onChange={this.handlechange}
          value={this.state.course.title}
        />
        <input type='submit' value='save' />
      </form>
    );
  }
}

Solution

The issue here is not we what expect i.e. ‘Cannot read property ‘state’ of undefined’, There are 3 approaches in context binding in react.

 handlechange() {
    const course = { …this.state.course, title: event.target.value };
     this.setState({ course });
}

Approach 1: Bind ‘this‘ context to own instance Less preferred

class CoursePage extends React.Component {
  state = {
    course: {
      title: '',
    },

  };
handlechange() {
    const course = { …this.state.course, title: event.target.value };
     this.setState({ course });
}
render(){
    return (
      <form>
			<h2>courses</h2>
			<h3>Add course</h3>
			<input
			type=’text’
			onChange={this.handlechange.bind(this)}
			value={this.state.course.title}
			/>
			<input type=’submit’ value=’save’ />
	  </form> 
		);
  }
}	

This works, because now this context bound to our class context, i.e {this.handlechange.bind(this)} to the onChange event, but It will cause to create an in-function unnecessarily on each render…

Approach 2 : Binding in the ConstructorLess preferred than Arrow function

The most common approach will be to do it in the constructor because it runs only once, now the function is bound only once, this is called context-binding in the constructor, this approach is preferable, won’t be reallocated on each render

class CoursePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      course: {
        title: "",
      },
    };
    //binding in constuctor 
    this.handlechange= this.handlechange.bind(this);
  };

handlechange() {
    const course = { …this.state.course, title: event.target.value };
     this.setState({ course });
}
return (
      <form>
			<h2>courses</h2>
			<h3>Add course</h3>
			<input
			type=’text’
			onChange={this.handlechange}
			value={this.state.course.title}
			/>
			<input type=’submit’ value=’save’ />
	  </form> 
		);
  }
}	

performance wise it is better to bind in the constructor. The bind in constructor method will create a single instance of the function and re-use it, even if the render method is called multiple times

Approach 3Arrow functionsMore preferred

Inherit the binding context of their enclosing scope. basically, they don’t have ‘this’ binding,  ‘this’ keyword inside references the class instance.

class CoursePage extends React.Component {
  state = { course: { title: '' } };
  handlechange = (event) => {
    const course = { ...this.state.course, title: event.target.value };
    this.setState({ course });
  };
  render() {
    return (
      <form>
        <h2>courses</h2>
        <h3>Add course</h3>
        <input
          type='text'
          onChange={this.handlechange}
          value={this.state.course.title}
        />
        <input type='submit' value='save' />
      </form>
    );
  }
Tip: How the Arrow function preferred in react state to achieve context binding?

Arrow functions are great. They do look nicer, But there is a much better reason to use arrow functions.  It would be more efficient if we know, when and where you are using it.    

handlechange = (event) => {
    const course = { ...this.state.course, title: event.target.value };
    this.setState({ course });
  }; 

In above case, the arrow function does not recreate function on each render, Similar to how binding in the constructor works in 2nd approach.

                                

Default image
Shivaraju M
Over 3+ years experience in IT industry, good knowledge in . Net-based Web applications, windows applications, web services, and SPAs. I have played multiple roles related to technical delivery in multiple domains while working on over 10+ technologies. I am currently focused on continuous improvement and agile project management.

Leave a Reply