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

JavascriptReactjsEcmascript 6Ecmascript 2016

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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

onChange={this.setAuthorState.bind(this)}

Solution 2 - Javascript

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}
      />
    );
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKhpalwalkView Question on Stackoverflow
Solution 1 - Javascriptmadox2View Answer on Stackoverflow
Solution 2 - JavascriptOleksandr T.View Answer on Stackoverflow