React with ES7: Uncaught TypeError: Cannot read property 'state' of undefined

151,142

Solution 1

Make sure you're calling super() as the first thing in your constructor.

You should set this for setAuthorState method

class ManageAuthorPage extends Component {

  state = {
    author: { id: '', firstName: '', lastName: '' }
  };

  constructor(props) {
    super(props);
    this.handleAuthorChange = this.handleAuthorChange.bind(this);
  } 

  handleAuthorChange(event) {
    let {name: fieldName, value} = event.target;

    this.setState({
      [fieldName]: value
    });
  };

  render() {
    return (
      <AuthorForm
        author={this.state.author}
        onChange={this.handleAuthorChange}
      />
    );
  }
}

Another alternative based on arrow function:

class ManageAuthorPage extends Component {

  state = {
    author: { id: '', firstName: '', lastName: '' }
  };

  handleAuthorChange = (event) => {
    const {name: fieldName, value} = event.target;

    this.setState({
      [fieldName]: value
    });
  };

  render() {
    return (
      <AuthorForm
        author={this.state.author}
        onChange={this.handleAuthorChange}
      />
    );
  }
}

Solution 2

You have to bind your event handlers to correct context (this):

onChange={this.setAuthorState.bind(this)}
Share:
151,142
Khpalwalk
Author by

Khpalwalk

Updated on July 05, 2022

Comments

  • Khpalwalk
    Khpalwalk almost 2 years

    I'm getting this error Uncaught TypeError: Cannot read property 'state' of undefined whenever I type anything in the input box of AuthorForm. I'm using React with ES7.

    The error occurs on 3rd line of setAuthorState function in ManageAuthorPage. Regardless of that line of code even if I put a console.log(this.state.author) in setAuthorState, it will stop at the console.log and call out the error.

    Can't find similar issue for someone else over the internet.

    Here is the ManageAuthorPage code:

    import React, { Component } from 'react';
    import AuthorForm from './authorForm';
    
    class ManageAuthorPage extends Component {
      state = {
        author: { id: '', firstName: '', lastName: '' }
      };
    
      setAuthorState(event) {
        let field = event.target.name;
        let value = event.target.value;
        this.state.author[field] = value;
        return this.setState({author: this.state.author});
      };
    
      render() {
        return (
          <AuthorForm
            author={this.state.author}
            onChange={this.setAuthorState}
          />
        );
      }
    }
    
    export default ManageAuthorPage 
    

    And here is the AuthorForm code:

    import React, { Component } from 'react';
    
    class AuthorForm extends Component {
      render() {
        return (
          <form>
                    <h1>Manage Author</h1>
            <label htmlFor="firstName">First Name</label>
                    <input type="text"
                        name="firstName"
              className="form-control"
                        placeholder="First Name"
              ref="firstName"
              onChange={this.props.onChange}
                        value={this.props.author.firstName}
              />
            <br />
    
            <label htmlFor="lastName">Last Name</label>
                    <input type="text"
                        name="lastName"
              className="form-control"
                        placeholder="Last Name"
              ref="lastName"
                        onChange={this.props.onChange}
              value={this.props.author.lastName}
                        />
    
                    <input type="submit" value="Save" className="btn btn-default" />
                </form>
        );
      }
    }
    
    export default AuthorForm
    
  • Khpalwalk
    Khpalwalk over 8 years
    I used your example mate. Thanks.
  • madox2
    madox2 over 8 years
    @Khpalwalk You are welcome :-)
  • Brett Reinhard
    Brett Reinhard almost 7 years
    I find a more eloquent way of doing this is by using arrow functions which will inherently bind this to the function, I find it especially useful when writing react code. So you can use setAuthorState=event=>{...}. No extra lines of code are necessary to bind this to the function. Also, every time this component is clicked it doesn't require the extra costs of binding this.
  • madox2
    madox2 almost 7 years
    @BrettReinhard you are right, currently that's probably the most convenient way. Anyway, JS programmers need to understand the reason of context binding
  • Brett Reinhard
    Brett Reinhard almost 7 years
    I agree, I feel as though 'this' eludes many developers and they don't fully understand what 'this' truly represents. I feel as though in react developers have a better understanding of 'this', now whether that is purely superficial is another thing. For those that don't understand 'this' should take a look at Kyle Simpsons , you don't know js repo on github. His username is getify, and has a few chapters dedicated to 'this' that will help get the ball rolling in understanding what 'this' means in the given context.
  • Faris Rayhan
    Faris Rayhan about 6 years
    yes thank u it is working for me. I forgot to to use bind in my code.
  • Faris Rayhan
    Faris Rayhan about 6 years
    yes thank u it is working for me. I forgot to to use bind in my code.
  • Sumit Ghewade
    Sumit Ghewade about 4 years
    alternative method worked for me Thanks for the answer
  • imran haider
    imran haider about 3 years
    do that in your constructor