How do I edit multiple input controlled components

2019-01-21 06:11发布

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

7条回答
仙女界的扛把子
2楼-- · 2019-01-21 06:20

<input> elements often have a property called name. We can access this name property from the event object that we receive from an event handler:

Write a generalized change handler

constructor () {
    super();
    this.state = {
      name: '',
      age: ''
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange (evt) {      
    this.setState({ [evt.target.name]: evt.target.value });
  }

render () {
    return (
      <form>

        <label>Name</label>
        <input type="text" name="name" onChange={this.handleChange} />

        <label>Age</label>
        <input type="text" name="age" onChange={this.handleChange} />

      </form>
    );
  }

source

查看更多
贪生不怕死
3楼-- · 2019-01-21 06:22

ES6 one liner approach

<input type="text" 
       value={this.state.username}
       onChange={(e) => this.setState({ username: e.target.value })}
       id="username"/>
查看更多
老娘就宠你
4楼-- · 2019-01-21 06:23

The neatest approach

Here is an approach that I used in my simple application. This is the recommended approach in React and it is really neat and clean. It is very close to ArneHugo's answer and I thank hm too. The idea is a mix of that and react forms site. We can use name attribute of each form input to get the specific propertyName and update the state based on that. This is my code in ES6 for the above example:

class ContactEdit extends React.Component {

  handleChangeFor = (event) => {
    const name = event.target.name;
    const value = event.target.value;
    const { contact } = this.state;
    const newContact = {
      ...contact,
      [name]: value
    };
    this.setState({ contact: newContact });
  }

  render() {
    return (
      <div>
        <input type="text" name="firstName" onChange={this.handleChangeFor} />
        <input type="text" name="lastName" onChange={this.handleChangeFor}/>
        <input type="text" name="phone" onChange={this.handleChangeFor}/>
      </div>
    );
  }
}

The differences:

  • We don't need to assign state as value attribute. No value is needed
  • The onChange method does not need to have any argument inside the function call as we use name attribute instead
  • We declare name and value of each input in the begening and use them to set the state properly in the code and we use rackets for name as it is an attribute.

We have less code here and vey smart way to get any kind input from the form because the name attribute will have a unique value for each input. See a working example I have in CodPen for my experimental blog application in its early stage.

查看更多
老娘就宠你
5楼-- · 2019-01-21 06:30
handleChange(event){
    this.setState({[event.target.name]:event.target.value});
    this.setState({[event.target.name]:event.target.value});
  }
查看更多
【Aperson】
6楼-- · 2019-01-21 06:36

There are two ways to update the state of a nested object:

  1. Use JSON.parse(JSON.stringify(object)) to create a copy of the object, then update the copy and pass it to setState.
  2. Use the immutability helpers in react-addons, which is the recommended way.

You can see how it works in this JS Fiddle. The code is also below:

var Component = React.createClass({
    getInitialState: function () {
    return ({contact: {firstName: "first", lastName: "last", phone: "1244125"}});
  },
  handleChange: function (key,event) {
    console.log(key,event.target.value);

    //way 1 
    //var updatedContact = JSON.parse(JSON.stringify(this.state.contact));
    //updatedContact[key] = event.target.value;

    //way 2 (Recommended)
    var updatedContact = React.addons.update(this.state.contact, {
        [key] : {$set: event.target.value}
    });
    this.setState({contact: updatedContact});
  },
  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.phone}/>
        </div>
      );
    }
});

ReactDOM.render(
  <Component />,
  document.getElementById('container')
);
查看更多
男人必须洒脱
7楼-- · 2019-01-21 06:45

Here is generic one;

handleChange = (input) => (event) => {
    this.setState({
        ...this.state,
        [input]: event.target.value
    });
}

And use like this;

<input handleChange ={this.handleChange("phone")} value={this.state.phone}/>
查看更多
登录 后发表回答