akantoword akantoword - 1 month ago 19
React JSX Question

How do I edit multiple input controlled components in React?

I have a component that stores a contact object as state - {firstName: "John", lastName: "Doe", phone: "1234567890} I want to create a form to edit this object but if I want the inputs to hold the value of the original contact parameter, I need to make each input a controlled component. However, I don't know how to create a handleChange function that will adjust to each parameter because my state only holds {contact: {...}}. Below is what I currently have -

getInitialState: function () {
return ({contact: {}});
},
handleChange: function (event) {
this.setState({contact: event.target.value });
},
render: function () {
return (
<div>
<input type="text" onChange={this.handleChange} value={this.state.contact.firstName}/>
<input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
<input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
</div>
);
}


I wish in my handleChange I can do something like

handleChange: function (event) {
this.setState({contact.firstName: event.target.value });
}

Answer

There's a "simple" way to do this, and a "smart" way. If you ask me, doing things the smart way is not always the best, because I may be harder to work with later. In this case, both are quite understandable.

Side note: One thing I'd ask you to think about, is do you need to update the contact object, or could you just keep firstName etc. directly on state? Maybe you have a lot of data in the state of the component? If that is the case, it's probably a good idea to separate it into smaller components with narrower responsibilities.

The "simple" way

    changeFirstName: function (event) {
      const contact = this.state.contact;
      contact.firstName = event.target.value;
      this.setState({contact: contact });
    },
    changeLastName: function (event) {
      const contact = this.state.contact;
      contact.lastName = event.target.value;
      this.setState({contact: contact });
    },
    changePhone: function (event) {
      const contact = this.state.contact;
      contact.phone = event.target.value;
      this.setState({contact: contact });
    },
    render: function () {
      return (
        <div>
          <input type="text" onChange={this.changeFirstName.bind(this)} value={this.state.contact.firstName}/>
          <input type="text" onChange={this.changeLastName.bind(this)} value={this.state.contact.lastName}/>
          <input type="text" onChange={this.changePhone.bind(this)} value={this.state.contact.phone}/>
        </div>
      );
    }

The "smart" way

    handleChange: function (propertyName, event) {
      const contact = this.state.contact;
      contact[propertyName] = event.target.value;
      this.setState({contact: contact });
    },
    render: function () {
      return (
        <div>
          <input type="text" onChange={this.handleChange.bind(this, 'firstName')} value={this.state.contact.firstName}/>
          <input type="text" onChange={this.handleChange.bind(this, 'lastName')} value={this.state.contact.lastName}/>
          <input type="text" onChange={this.handleChange.bind(this, 'phone')} value={this.state.contact.lastName}/>
        </div>
      );
    }
Comments