forms - handlesubmit - ¿Cómo edito múltiples componentes controlados por entrada en React?
react select onchange (4)
Hay dos formas de actualizar el estado de un objeto anidado:
- Use JSON.parse (JSON.stringify (object)) para crear una copia del objeto, luego actualice la copia y páselo a setState.
- Utilice los ayudantes de inmutabilidad en react-addons , que es la forma recomendada.
Puedes ver cómo funciona en este JS Fiddle . El código también está debajo:
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'')
);
Tengo un componente que almacena un objeto de contacto como estado - {firstName: "John", lastName: "Doe", teléfono: "1234567890} Quiero crear un formulario para editar este objeto, pero si quiero que las entradas tengan el valor del parámetro de contacto original, necesito hacer que cada entrada sea un componente controlado. Sin embargo, no sé cómo crear una función handleChange que se ajustará a cada parámetro porque mi estado solo tiene {contact: {...}}. Debajo está lo que tengo actualmente:
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>
);
}
Deseo en mi mangoCambio puedo hacer algo como
handleChange: function (event) {
this.setState({contact.firstName: event.target.value });
}
ES6 one liner approach
<input type="text"
value={this.state.username}
onChange={(e) => this.setState({ username: e.target.value })}
id="username"/>
Hay una manera "simple" de hacer esto, y una manera "inteligente". Si me preguntas, hacer las cosas de la manera más inteligente no siempre es lo mejor, porque es posible que sea más difícil trabajar más tarde. En este caso, ambos son bastante comprensibles.
Nota al margen: una cosa en la que le pediría que piense, ¿necesita actualizar el objeto de contact
, o podría simplemente mantener el primer nombre, etc. directamente en estado? Tal vez tienes muchos datos en el estado del componente? Si ese es el caso, probablemente sea una buena idea separarlo en componentes más pequeños con responsabilidades más limitadas.
La forma "simple"
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>
);
}
La forma "inteligente"
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>
);
}
Actualización: los mismos ejemplos usando ES2015 +
Esta sección contiene los mismos ejemplos que se muestran arriba, pero usando características de ES2015 +.
Para admitir las siguientes funciones en todos los navegadores, debe transponer su código con Babel utilizando, por ejemplo, los ajustes preestablecidos es2015 y reaccionar , y el complemento stage-0 .
A continuación hay ejemplos actualizados, utilizando la desestructuración de objetos para obtener el contacto del estado, el operador de difusión para crear un objeto de contacto actualizado en lugar de mutar el existente, crear componentes como clases al extender el componente React.Component y usar funciones de flecha para crear devoluciones de llamadas para que podamos no tiene que bind(this)
.
La forma "simple", 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>
);
}
}
La forma "inteligente", ES2015 +
Tenga en cuenta que handleChangeFor
es una función handleChangeFor
: al llamarlo con un propertyName
crea una función de devolución de llamada que, cuando se handleChangeFor
, actualiza [propertyName]
del objeto de contacto (nuevo) en el estado.
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>
);
}
}
Aquí hay uno genérico;
handleChange = (input) => (event) => {
this.setState({
...this.state,
[input]: event.target.value
});
}
Y usar así;
<input handleChange ={this.handleChange("phone")} value={this.state.phone}/>