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

How do I edit multiple input controlled components in React?

本文关键字:输入 控制 组件 编辑 React      更新时间:2023-09-26

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

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

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

旁注:我想请您考虑的一件事是,您是否需要更新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>
    );
  }

"智能"方式

  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 转译您的代码,例如:预设 ES2015 并做出反应,和插件阶段-0。

下面是更新的示例,使用对象解构从状态获取联系人,传播运算符到创建一个更新的联系人对象,而不是改变现有的联系人对象,将组件创建为类扩展 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>
    );
  }
}

"智能"方式,ES2015+

请注意,handleChangeFor是一个柯里函数:使用 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>
    );
  }
}

ES6 单行方法

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

最简洁的方法

这是我在简单应用程序中使用的一种方法。这是 React 中推荐的方法,它非常整洁干净。这与阿内雨果的回答非常接近,我也感谢嗯。这个想法是那个和反应形式的混合。我们可以使用每个表单输入的 name 属性来获取特定的属性 Name 并在此基础上更新状态。这是我在 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>
    );
  }
}

区别:

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

我们这里的代码较少,并且非常聪明地从表单中获取任何类型的输入,因为 name 属性对于每个输入都有一个唯一的值。请参阅我在CodPen中为我的实验性博客应用程序在其早期阶段提供的工作示例。

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

  1. 使用 JSON.parse(JSON.stringify(object)) 创建对象的副本,然后更新副本并将其传递给 setState。
  2. 在 react-adddons 中使用不可变性帮助器,这是推荐的方法。

你可以在这个JS小提琴中看到它是如何工作的。 代码也如下:

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

这是通用的;

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

并像这样使用;

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

<input>元素通常具有一个名为name的属性。我们可以从从事件处理程序接收的事件对象访问此 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>
    );
  }

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

您可以在没有重复代码和简单方法的情况下做到这一点

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>
handleChange(event){
    this.setState({[event.target.name]:event.target.value});
    this.setState({[event.target.name]:event.target.value});
  }