簡體   English   中英

如何在 React 中編輯多個輸入控制組件?

[英]How do I edit multiple input controlled components in React?

我有一個組件將聯系人對象存儲為狀態 - {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 我可以做類似的事情

  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轉譯您的代碼,例如使用預設es2015react以及插件stage-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是一個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"/>

有兩種方法可以更新嵌套對象的狀態:

  1. 使用 JSON.parse(JSON.stringify(object)) 創建對象的副本,然后更新副本並將其傳遞給 setState。
  2. 使用react-addons 中不變性助手,這是推薦的方式。

你可以在這個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')
);

最簡潔的方法

這是我在我的簡單應用程序中使用的一種方法。 這是React 中推薦的方法,它非常簡潔。 它非常接近 ArneHugo 的回答,我也很感謝。 這個想法是它和反應形式站點的混合。 我們可以使用每個表單輸入的 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>
    );
  }
}

區別:

  • 我們不需要將狀態分配為值屬性。 不需要值
  • onChange 方法不需要在函數調用中包含任何參數,因為我們使用 name 屬性代替
  • 我們在開始時聲明每個輸入的名稱和值,並使用它們在代碼中正確設置狀態,我們使用球拍作為名稱,因為它是一個屬性。

我們這里的代碼較少,並且可以通過非常聰明的方式從表單中獲取任何類型的輸入,因為 name 屬性對於每個輸入都有一個唯一的值。 請參閱我在 CodPen 中為我的早期實驗性博客應用程序提供的工作示例

這是通用的;

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM