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

时间:2016-03-13 01:01:03

标签: forms input reactjs components

我有一个将联系人对象存储为状态的组件 - {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>
      );
    }

我希望在我的处理中改变我可以做类似

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

9 个答案:

答案 0 :(得分:58)

有一个&#34;简单&#34;这样做的方式,以及&#34; smart&#34;办法。如果你问我,以聪明的方式做事并不总是最好的,因为我以后可能会更难以合作。在这种情况下,两者都是可以理解的。

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

&#34;简单&#34;方式

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

&#34; smart&#34;方式

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



更新:使用ES2015 +

的相同示例

此部分包含与上面显示的相同的示例,但使用ES2015 +。

中的功能

要在不同浏览器中支持以下功能,您需要使用Babel使用以下功能来转换代码: 预设es2015react, 和插件stage-0

以下是更新的示例,使用object destructuring获取州的联系人, spread operator来 创建一个更新的联系对象而不是改变现有的联系对象, 将组件创建为Classes 延伸React.Component, 并使用arrow funtions来 创建回调,以便我们不必bind(this)

&#34;简单&#34;方式, 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>
    );
  }
}

&#34; smart&#34;方式, ES2015 +

请注意,handleChangeForcurried function: 使用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>
    );
  }
}

答案 1 :(得分:8)

ES6单线方法

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

答案 2 :(得分:2)

有两种方法可以更新嵌套对象的状态:

  1. 使用JSON.parse(JSON.stringify(object))创建对象的副本,然后更新副本并将其传递给setState。
  2. 使用immutability helpers in react-addons,这是推荐的方法。
  3. 您可以在此JS Fiddle中查看其工作原理。代码如下:

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

答案 3 :(得分:1)

这是通用的;

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

并像这样使用;

<input handleChange ={this.handleChange("phone")} value={this.state.phone}/>

答案 4 :(得分:1)

最整洁的方法

这是我在简单应用程序中使用的一种方法。这是React中推荐的方法,它确实干净利落。这非常接近ArneHugo的回答,我也感谢hm。这个想法是混合和反应形式站点。 我们可以使用每个表单输入的name属性来获取特定的propertyName并基于此更新状态。这是我在ES6中的上述示例代码:

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

差异:

  • 我们不需要将状态分配为value属性。不需要任何值
  • onChange方法在函数调用中不需要任何参数,因为我们改用name属性
  • 我们在开始步骤中声明每个输入的名称和值,并使用它们在代码中正确设置状态,并且使用球拍作为名称,因为它是属性。

我们在这里使用的代码更少,并且提供了从表单获取任何类型输入的明智方法,因为name属性对于每个输入将具有唯一的值。 在早期阶段,可以在我的CodPen中进行实验性博客应用程序的工作example

答案 5 :(得分:0)

<input> 元素通常具有一个名为name的属性。 我们可以从事件处理程序收到的事件对象中访问此名称属性:

编写通用的更改处理程序

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

答案 6 :(得分:0)

updatePrevData=(event)=>{
    let eventName=event.target.name;
   this.setState({
       ...this.state,
       prev_data:{
        ...this.state.prev_data,
        [eventName]:event.target.value
       }

   })

   console.log(this.state)

}

答案 7 :(得分:0)

您可以做到,无需重复的代码和简单的方法

handleChange=(e)=>{
    this.setState({
        [e.target.id]:e.target.value
    })
}


<Form.Control type="text" defaultValue={this.props.allClients.name}  id="clientName"  onChange={this.handleChange}></Form.Control>
<Form.Control type="email" defaultValue={this.props.allClients.email}  id="clientEmail"  onChange={this.handleChange}></Form.Control>

答案 8 :(得分:-2)

handleChange(event){
    this.setState({[event.target.name]:event.target.value});
    this.setState({[event.target.name]:event.target.value});
  }