javascript - rails - react tutorial
La mejor práctica para los componentes de la forma ReactJS (1)
- Todo lo que va a cambiar entra en estado.
- Si está buscando cargar una entidad existente y editarla, quiere entradas controladas, y desea establecer los valores en consecuencia. En la mayoría de los casos, me mantengo alejado de defaultValue (fuera de los menús desplegables)
- Esto se relaciona con tu pregunta anterior. Si especifica un valor, está utilizando una entrada controlada, y debe proporcionar un controlador onChange para cualquier entrada controlada; de lo contrario, se establece en piedra. Un beneficio de las entradas controladas es que los usuarios no pueden editarlas, por lo que si tiene algunas propiedades bloqueadas (tal vez solo por razones de seguridad), cuando el usuario intenta guardar, incluso si editó el HTML directamente, Reaccionar debería tirar el valor de la propiedad de la representación vDOM (podría estar mal aquí, pero creo que lo he probado antes). De todos modos, debes tener activado el Cambio directamente en las entradas controladas. En cuanto al uso de la delegación de eventos (en el nivel de formulario), esto no es una mala práctica para muchos eventos, este es solo un escenario específico (entradas controladas) donde se necesitan eventos de Cambio especificados para cada elemento.
- No estoy del todo seguro de lo que pregunto en este caso, pero utilicé refs en lugar de target.name.
- Entonces, tienes razón en que nunca debes alterar el estado directamente, y esto es un poco difícil de los documentos. React va a alterar el estado directamente, solo lo hará en la implementación a través de setState. Si modifica el estado fuera de esta llamada a método, sucederán cosas inesperadas y se lanzarán errores.
shouldComponentUpdate solo hace comparaciones superficiales, pero hay algunas soluciones aquí.
Una es codificar los objetos, esta es una comparación de objeto rápida y sucia, realmente no lo recomiendo, pero funciona.
Una solución mejor, y una que he usado con React + Flux es implementar un bool PropertyChanged, y simplemente verificarlo en su shouldComponentUpdate.
Ahora, esto requerirá que tenga en cuenta establecerlo cuando las cosas cambien, es decir, que haya cambiado algo más profundo en el gráfico de objetos. Diga propiedadOne es un objeto con una propiedad que cambia en su método handleChange. Validará la entrada como lo desee, luego establezca propertyChanged = true, y luego deberá implementar componentDidUpdate . Estamos haciendo una suposición aquí, pero si el componente se ha actualizado, estableces propertyChanged en false para que no tengas ninguna activación adicional de actualizaciones no deseadas. Espero que tenga sentido. Es como un notifyPropertyChanged de un solo sentido.
Proporciono un ejemplo rápido de lo que probablemente haría para una implementación más dinámica que le permite agregar más propiedades a su objeto (solo propiedades superficiales en esta implementación, obviamente, podría escribir una solución más robusta). Avíseme si tiene más preguntas o si no respondí algo.
var e = {
prop1: ''test'',
prop2: ''wee'',
prop3: ''another property'',
propFour: ''Oh yeah!''
};
var FormComp = React.createClass({
getInitialState: function(){
return {
entity: this.props.entity
}
},
render: function() {
var ent = this.state.entity;
var that = this;
var inputs = [];
for(var key in ent){
inputs.push(<input
key={key}
style={{display:''block''}}
type="text"
ref={key} onChange={that._propertyChanged.bind(null, key)}
value={ent[key]} />)
}
return <form>
{inputs}
<input
type="button"
onClick={this._saveChanges}
value="Save Changes" />
</form>;
},
_propertyChanged: function(propName) {
var nextProp = this.refs[propName].getDOMNode().value;
var nextEntity = this.state.entity;
nextEntity[propName] = nextProp;
this.setState({
entity: nextEntity
});
},
_saveChanges: function() {
var updatedEntity = this.state.entity;
for(var key in updatedEntity){
alert(updatedEntity[key]);
}
//TODO: Call to service to save the entity, i.e.
ActionCreators.saveEntity(updatedEntity);
}
});
React.renderComponent(<FormComp entity={e} />, document.body);
Estoy buscando una mejor práctica para tener un componente ReactJS responsable del formulario para que los usuarios editen una entidad determinada. Ejemplo muy simplificado aquí. Las formas reales tendrían en muchos casos varios campos más y más funcionalidad GUI.
React.createClass({
getInitialState: function() {
return {
entity: {
property1: null,
property2: null
}
};
},
handleChange: function(e) {
var entity = this.state.entity;
switch(e.target.name) {
case ''property1'':
entity.property1 = e.target.value;
break;
case ''property2'':
entity.property2 = e.target.value;
break;
}
this.setState({
entity: entity
});
},
render: function() {
return (
<div className="entity-form">
<form onChange={this.handleChange}>
<input type="text" name="property1" value={this.state.entity.property1} />
<br />
<textarea name="property2" value={this.state.entity.property2}></textarea>
<br />
</form>
</div>
);
}
});
Los campos del formulario están editando directamente un objeto de entidad, que luego podría guardarse en una API REST. Quiero que el componente se actualice a medida que el usuario cambia los campos, por lo que la GUI podría reaccionar en función de la entrada durante el tipeo (como validaciones, información, etc.).
En teoría, podría hacer que todo el objeto de estado representara a la entidad que se está editando, de modo que cada propiedad de la entidad es de primer nivel. Sin embargo, quiero poder agregar variables de estado adicionales para funciones de GUI y otras cosas relacionadas con lo que el componente va a hacer, por lo que preferiría que el objeto de entidad fuera una variable de estado como la variable de estado "entidad" anterior. El objeto podría ser, por supuesto, un objeto más complicado, como un modelo Backbone o similar, pero en este ejemplo simplificado, simplemente uso un objeto simple con las propiedades requeridas.
Entonces, en busca de la mejor manera de hacer los componentes de React para este propósito, tengo algunas preguntas:
- Apoyos o estado.
En este caso, he elegido poner el objeto de entidad con el contenido para el formulario en una variable de estado en lugar de prop. Esto es para poder actualizar el objeto durante la entrada del formulario sin tener que llamar al padre y actualizar los accesorios. En lo que respecta a mi experiencia React, esa sería la mejor práctica para un componente de formulario como este.
- Entradas controladas o no controladas.
En el ejemplo simplificado anterior, uso entradas controladas. Esto lleva a actualizar el estado y volver a representar el componente en cada cambio (como cada carácter ingresado de un campo de texto). ¿Es esta la mejor práctica? Lo bueno es que el componente tiene control total de lo que sucede, en lugar de tener parámetros de Valor por defecto, y en algún evento (como que el usuario presione un botón de guardar), el componente extrae los valores, actualiza la entidad y la guarda en el servidor. ¿Hay alguna razón (u opinión) sobre si se deben usar entradas controladas o no controladas en casos como este?
- onChange para la forma o cada entrada
El ejemplo tiene un onChange en la etiqueta de formulario, y hace que se llame al método handleChange cada vez que se cambia cualquiera de los campos en el formulario. Sin embargo, dado que las entradas están controladas (tienen parámetros de valor), React se queja de que los campos de entrada no tienen una propiedad onChange. ¿Esto significa que tener un onChange común en la etiqueta del formulario es una mala práctica, y debería eliminarlo y poner en cambio el cambio en cada campo individual?
- Actualización de propiedades individuales
En el ejemplo anterior, utilizo un conmutador basado en qué campo de entrada se actualiza (cuando se llama a handleChange). Supongo que podría asegurarme de que todos los nombres de campo estén sincronizados con los nombres de propiedad de la entidad, y puedo establecer las propiedades del objeto de entidad en handleChange en función del nombre del campo del evento (e.target.name). Sin embargo, esto hace que sea difícil tener necesidades individuales por campo, incluso si la mayoría de los campos simplemente actualiza una propiedad de entidad directamente. Supongo que un alternativ es un interruptor con una configuración de bloque predeterminada basada en el nombre de la entrada y bloques de casos para cualquier campo que requiera otras formas de actualización (como filtrar el valor antes de configurarlo en la entidad). Coméntelo si conoce alguna forma mucho mejor de gestionar las actualizaciones de campo de esta manera.
- Actualizando la entidad del estado
Un gran problema de este ejemplo es la forma en que se actualiza el objeto de la entidad. Dado que la variable de entidad en handleChange se establece en el objeto de entidad desde el estado actual, esto es solo un puntero, y la actualización de la variable de entidad cambiará el objeto en estado. Las páginas de React dicen que nunca se debe actualizar el estado directamente. Una de las razones es algo que he experimentado al actualizar el estado de esta manera antes de llamar a setState. Si tiene un método shouldComponentUpdate, prevState contiene el nuevo estado, ya que el contenido del argumento prevState enviado a shouldComponentUpdate se basa en lo que estaba en el estado cuando se llamó a setState. Hasta donde yo sé, no hay una forma simple de clonar un objeto en javascript. Entonces, la pregunta es: cuando tengo objetos enteros que necesito para actualizar las propiedades de (y no tocar los otros valores en el objeto) en lugar de simplemente ejecutar setState de una sola variable de estado, ¿cuál es la mejor manera de hacerlo sin causar estos tipos? de las confusiones de estado?