如何在React中编辑多个输入控制组件?

aka*_*ord 29 forms components input reactjs

我有一个组件将联系人对象存储为状态 - {firstName:"John",lastName:"Doe",phone:"1234567890}我想创建一个表单来编辑这个对象,但是如果我希望输入保存值原始的联系参数,我需要使每个输入成为受控组件.但是,我不知道如何创建一个handleChange函数来调整每个参数,因为我的状态只保存{contact:{...}}.以下是我目前的情况 -

  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>
      );
    }
Run Code Online (Sandbox Code Playgroud)

我希望在我的处理中改变我可以做的事情

  handleChange: function (event) {
    this.setState({contact.firstName: event.target.value });
  }
Run Code Online (Sandbox Code Playgroud)

Arn*_*ugo 60

这是一种"简单"的方式,也是一种"聪明"的方式.如果你问我,以聪明的方式做事并不总是最好的,因为我以后可能会更难以合作.在这种情况下,两者都是可以理解的.

旁注:我要求您考虑的一件事是,您是否需要更新contact对象,或者您是否可以firstName直接保持等状态?也许你在组件的状态中有很多数据?如果是这种情况,将它分成较小的组成部分可能是一个好主意,责任范围较窄.

"简单"的方式

  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>
    );
  }
Run Code Online (Sandbox Code Playgroud)

"聪明"的方式

  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>
    );
  }
Run Code Online (Sandbox Code Playgroud)



更新:使用ES2015 +的相同示例

本节包含与上面显示的相同的示例,但使用ES2015 +中的功能.

要在浏览器中支持以下功能,您需要使用例如预设es2015react以及插件阶段0来使用Babel来转换代码.

下面是更新的示例,使用对象解构来从状态获取联系, 扩展运算符创建更新的联系对象而不是改变现有的联系对象,通过扩展React.Component创建组件作为,并使用箭头功能创建回调,以便我们不必.bind(this)

"简单"的方式,ES2015 +

class ContactEdit extends React.Component {

  changeFirstName = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      firstName: event.target.value
    };
    this.setState({ contact: newContact });
  }
  changeLastName = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      lastName: event.target.value
    };
    this.setState({ contact: newContact });
  }
  changePhone = (event) => {
    const { contact } = this.state;
    const newContact = {
      ...contact,
      phone: event.target.value
    };
    this.setState({ contact: newContact });
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.changeFirstName} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.changeLastName} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.changePhone} value={this.state.contact.phone}/>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

"智能"方式,ES2015 +

请注意,这handleChangeFor是一个curried函数:使用a调用它propertyName会创建一个回调函数,该函数在被调用时会更新状态[propertyName]中的(新)联系对象.

class ContactEdit extends React.Component {

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

  render() {
    return (
      <div>
        <input type="text" onChange={this.handleChangeFor('firstName')} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.handleChangeFor('lastName')} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.handleChangeFor('phone')} value={this.state.contact.lastName}/>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 如何在handleChange中使用e.target.name(当然,在输入上设置'name'属性),这样就可以省略第二个参数 (5认同)
  • 我认为你已经将handleChange中参数的顺序颠倒为"智能"方式.不应该是:(propertyName,event)而不是(event,propertyName)? (3认同)

Stu*_* P. 8

ES6单线程方法

<input type="text" 
       value={this.state.username}
       onChange={(e) => this.setState({ username: e.target.value })}
       id="username"/>
Run Code Online (Sandbox Code Playgroud)