How to change parent state from children in React?

- 1 answer

Ad

I want to write a small user list with four columns that have an edit possibility.

So far I everything went fine. In my parent component I add an object to my state that has some dummy user data. I then render the data through a child component. In the child element I use its state to change text fields to input fields.

Now I want to change the state of the parent in order to reflect the changes made in the input fields.

Parent component:

editUser(username, firstName, lastName, email, createdAt, key) {
  this.setState({ // THIS LINE WILL THROW AN ERROR
    users[key]: {
      username: username,
      firstName: firstName,
      lastName: lastName,
      email: email,
      createdAt: createdAt
    }
  }); 
}

render() {
  return (
    <div>
      <table width="100%">
        <thead>
          <tr>
            ...
          </tr>
        </thead>
        <tbody>
          {_.map(this.state.users, (entry, key) => {
            return <UserEntry editUser={this.editUser} username={entry.username} firstName={entry.firstName} lastName={entry.lastName} email={entry.email} createdAt={entry.createdAt} key={key}/>
          })}
        </tbody>
      </table>
    </div>
  );
}

Child component:

isEdit(e) {
  this.setState({ editable: true });
}

changeValue(username, firstName, lastName, email, createdAt, key) {
  this.setState({ editable: false });
  this.props.editUser(username, firstName, lastName, email, createdAt, key);
}

render() {
  const {username, firstName, lastName, email, createdAt} = this.props;
  if (this.state.editable) {
    return (
      <tr>
        <td><input type="text" defaultValue={username}/></td>
        <td><input type="text" defaultValue={firstName}/></td>
        <td><input type="text" defaultValue={lastName}/></td>
        <td><input type="text" defaultValue={email}/></td>
        <td><input type="text" defaultValue={createdAt}/></td>
        <td><button onClick={this.changeValue.bind(this, username, firstName, lastName, email, createdAt, this.props.key)} type="button" value="Ok">Ok</button></td>
      </tr>
    )
  } else {
    return (
      <tr>
        <td>{username}</td>
        <td>{firstName}</td>
        <td>{lastName}</td>
        <td>{email}</td>
        <td>{createdAt}</td>
        <td><input onClick={this.isEdit.bind(this)} type="button" value="Edit"/></td>
      </tr>
    )
  }
}

The editUser method in my parent component will throw an error:

Uncaught TypeError: this.setState is not a function

What am I doing wrong?

Ad

Answer

Ad

I see you use ES6, you should have in the constructor of the parent element following line:

constructor() {
  this.editUser = this.editUser.bind(this);
}
Ad
source: stackoverflow.com
Ad