Javascript 如何在 React 中编辑多个输入控制组件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35965275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I edit multiple input controlled components in React?
提问by akantoword
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 -
我有一个将联系人对象存储为状态的组件 - {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>
);
}
I wish in my handleChange I can do something like
我希望在我的 handleChange 我可以做类似的事情
handleChange: function (event) {
this.setState({contact.firstName: event.target.value });
}
回答by ArneHugo
There's a "simple" way to do this, and a "smart" way. If you ask me, doing things the smart way is not always the best, because I may be harder to work with later. In this case, both are quite understandable.
有一种“简单”的方法可以做到这一点,还有一种“聪明”的方法。如果你问我,以聪明的方式做事并不总是最好的,因为以后可能会更难和我一起工作。在这种情况下,两者都是可以理解的。
Side note: One thing I'd ask you to think about, is do you need to update the contact
object, or could you just keep firstName
etc. directly on state? Maybe you have a lot of data in the state of the component? If that is the case, it's probably a good idea to separate it into smaller components with narrower responsibilities.
旁注:我要请您考虑的一件事是,您是否需要更新contact
对象,还是可以firstName
直接将等保持在状态?也许你有很多组件状态的数据?如果是这种情况,最好将其分成具有更窄职责的较小组件。
The "simple" way
“简单”的方式
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>
);
}
The "smart" way
“聪明”的方式
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>
);
}
Update: Same examples using ES2015+
更新:使用 ES2015+ 的相同示例
This section contains the same examples as shown above, but using features from ES2015+.
本节包含与上述相同的示例,但使用 ES2015+ 的功能。
To support the following features across browsers you need to transpile your code with Babelusing e.g. the presets es2015and react, and the plugin stage-0.
要在浏览器中支持以下功能,您需要使用Babel转译您的代码,例如使用预设es2015和react以及插件stage-0。
Below are updated examples, using object destructuringto get the contact from the state,
spread operatorto
create an updated contact object instead of mutating the existing one,
creating components as Classesby
extending React.Component,
and using arrow funtionsto
create callbacks so we don't have to bind(this)
.
下面是更新的示例,使用对象解构从状态中获取联系人,
扩展运算符创建更新的联系人对象而不是改变现有的对象,通过扩展React.Component将组件创建为类,并使用箭头函数创建回调,因此我们不必。bind(this)
The "simple" way, ES2015+
“简单”的方式,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>
);
}
}
The "smart" way, ES2015+
“智能”方式,ES2015+
Note that handleChangeFor
is a curried function:
Calling it with a propertyName
creates a callback function which, when called, updates [propertyName]
of the
(new) contact object in the state.
请注意,这handleChangeFor
是一个柯里化函数:使用 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>
);
}
}
回答by Stuart P.
ES6 one liner approach
ES6 一种线性方法
<input type="text"
value={this.state.username}
onChange={(e) => this.setState({ username: e.target.value })}
id="username"/>
回答by Mark
There are two ways to update the state of a nested object:
有两种方法可以更新嵌套对象的状态:
- Use JSON.parse(JSON.stringify(object)) to create a copy of the object, then update the copy and pass it to setState.
- Use the immutability helpers in react-addons, which is the recommended way.
- 使用 JSON.parse(JSON.stringify(object)) 创建对象的副本,然后更新副本并将其传递给 setState。
- 使用react-addons 中的不变性助手,这是推荐的方式。
You can see how it works in this JS Fiddle. The code is also below:
你可以在这个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')
);
回答by azad6026
The neatest approach
最简洁的方法
Here is an approach that I used in my simple application. This is the recommended approach in Reactand 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:
这是我在我的简单应用程序中使用的一种方法。这是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>
);
}
}
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.
- 我们不需要将状态分配为值属性。不需要值
- onChange 方法不需要在函数调用中包含任何参数,因为我们使用 name 属性代替
- 我们在开始时声明每个输入的名称和值,并使用它们在代码中正确设置状态,我们使用球拍作为名称,因为它是一个属性。
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 exampleI have in CodPen for my experimental blog application in its early stage.
我们这里的代码较少,并且可以通过非常聪明的方式从表单中获取任何类型的输入,因为 name 属性对于每个输入都有一个唯一的值。请参阅我在 CodPen 中为我的早期实验性博客应用程序提供的工作示例。
回答by Mohamed
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}/>
回答by Dhruv Raval
<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:
<input>
元素通常有一个名为 name 的属性。我们可以从我们从事件处理程序接收到的事件对象访问这个 name 属性:
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
来源
回答by Karan Chunara
handleChange(event){
this.setState({[event.target.name]:event.target.value});
this.setState({[event.target.name]:event.target.value});
}