script react helmet reactjs

reactjs - helmet - react meta tags



Actualización del estado en el cambio de accesorios en el Formulario de reacción (9)

Tengo problemas con un formulario React y con la administración adecuada del estado. Tengo un campo de entrada de tiempo en un formulario (en un modal). El valor inicial se establece como una variable de estado en getInitialState y se pasa desde un componente principal. Esto en sí mismo funciona bien.

El problema surge cuando quiero actualizar el valor predeterminado de start_time a través del componente principal. La actualización en sí ocurre en el componente principal a través de setState start_time: new_time . Sin embargo, en mi formulario, el valor predeterminado start_time nunca cambia, ya que solo se define una vez en getInitialState .

Intenté usar componentWillUpdate para forzar un cambio de estado a través de setState start_time: next_props.start_time , que realmente funcionó, pero me dio Uncaught RangeError: Maximum call stack size exceeded errores.

Entonces mi pregunta es, ¿cuál es la forma correcta de actualizar el estado en este caso? ¿Estoy pensando en esto mal de alguna manera?

Código actual:

@ModalBody = React.createClass getInitialState: -> start_time: @props.start_time.format("HH:mm") #works but takes long and causes: #"Uncaught RangeError: Maximum call stack size exceeded" componentWillUpdate: (next_props, next_state) -> @setState(start_time: next_props.start_time.format("HH:mm")) fieldChanged: (fieldName, event) -> stateUpdate = {} stateUpdate[fieldName] = event.target.value @setState(stateUpdate) render: -> React.DOM.div className: "modal-body" React.DOM.form null, React.createElement FormLabelInputField, type: "time" id: "start_time" label_name: "Start Time" value: @state.start_time onChange: @fieldChanged.bind(null, "start_time”) @FormLabelInputField = React.createClass render: -> React.DOM.div className: "form-group" React.DOM.label htmlFor: @props.id @props.label_name + ": " React.DOM.input className: "form-control" type: @props.type id: @props.id value: @props.value onChange: @props.onChange


Aparentemente las cosas están cambiando ... getDerivedStateFromProps() es ahora la función preferida.

class Component extends React.Component { static getDerivedStateFromProps(props, current_state) { if (current_state.value !== props.value) { return { value: props.value, computed_prop: heavy_computation(props.value) } } return null } }

(código anterior por danburzo @ github)


Creo que usar ref es seguro para mí, no necesito preocuparme por algún método anterior.

class Company extends XComponent { constructor(props) { super(props); this.data = {}; } fetchData(data) { this.resetState(data); } render() { return ( <Input ref={c => this.data[''name''] = c} type="text" className="form-control" /> ); } } class XComponent extends Component { resetState(obj) { for (var property in obj) { if (obj.hasOwnProperty(property) && typeof this.data[property] !== ''undefined'') { if ( obj[property] !== this.data[property].state.value ) this.data[property].setState({value: obj[property]}); else continue; } continue; } } }


De la documentación de reacción: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

El estado de borrado cuando los accesorios cambian es un Anti Patrón

Desde React 16, componentWillReceiveProps está en desuso. De la documentación de reacción, el enfoque recomendado en este caso es el uso

  1. Componente totalmente controlado: el ParentComponent de ModalBody será el propietario del estado start_time . Este no es mi enfoque preferido en este caso, ya que creo que el modal debería ser el propietario de este estado.
  2. Componente totalmente incontrolado con una clave: este es mi enfoque preferido. Un ejemplo de la documentación de reacción: https://codesandbox.io/s/6v1znlxyxn . Sería dueño del estado start_time de su ModalBody y usaría getInitialState tal como ya lo hizo. Para restablecer el estado start_time , simplemente cambie la clave del ParentComponent

Es bastante claro de sus documentos:

If you used componentWillReceiveProps for re-computing some data only when a prop changes, use a memoization helper instead.

Uso: reactjs.org/blog/2018/06/07/…


La nueva forma de hacerlo es usar useEffect en lugar de componentWillReceiveProps de la manera anterior:

componentWillReceiveProps(nextProps) { // You don''t have to do this check first, but it can help prevent an unneeded render if (nextProps.startTime !== this.state.startTime) { this.setState({ startTime: nextProps.startTime }); } }

se convierte en lo siguiente en un componente funcional impulsado por ganchos:

// store the startTime prop in local state const [startTime, setStartTime] = useState(props.startTime) // useEffect(() => { if (props.startTime !== startTime) { setStartTime(props.startTime); } }, [props.startTime]);

configuramos el estado usando setState, usando useEffect, verificamos los cambios en el accesorio especificado y tomamos la acción para actualizar el estado al cambiar el accesorio.


Si lo entiendo correctamente, ¿tiene un componente principal que está pasando start_time al componente ModalBody que lo asigna a su propio estado? Y desea actualizar ese tiempo desde el componente primario, no desde un componente secundario.

React tiene algunos consejos para lidiar con este escenario. (Tenga en cuenta que este es un artículo antiguo que desde entonces se ha eliminado de la web. Aquí hay un enlace al documento actual sobre accesorios de componentes ).

El uso de accesorios para generar estado en getInitialState menudo conduce a la duplicación de "fuente de verdad", es decir, dónde están los datos reales. Esto se debe a que getInitialState solo se invoca cuando el componente se crea por primera vez.

Siempre que sea posible, calcule los valores sobre la marcha para asegurarse de que no se desincronicen más adelante y causen problemas de mantenimiento.

Básicamente, cada vez que asigna los props de los padres al state un niño, el método de representación no siempre se llama en la actualización de accesorios. Debe invocarlo manualmente, utilizando el método componentWillReceiveProps .

componentWillReceiveProps(nextProps) { // You don''t have to do this check first, but it can help prevent an unneeded render if (nextProps.startTime !== this.state.startTime) { this.setState({ startTime: nextProps.startTime }); } }


También hay componentDidUpdate disponible.

Función firmante:

<EmailInput defaultEmail={this.props.user.email} key={this.props.user.id} />

Use esto como una oportunidad para operar en el DOM cuando el componente se haya actualizado. No se llama en el render inicial.

Consulte Probablemente no necesite el artículo de estado derivado , que describe Anti-Pattern tanto para componentDidUpdate como para getDerivedStateFromProps . Lo encontré muy útil.


Probablemente no necesite estado derivado

1. Establecer una clave del padre

Cuando una clave cambia, React creará una nueva instancia de componente en lugar de actualizar la actual. Las claves se usan generalmente para listas dinámicas, pero también son útiles aquí.

2. Utilice getDerivedStateFromProps / componentWillReceiveProps

Si la clave no funciona por alguna razón (quizás el componente es muy costoso de inicializar)

Al usar getDerivedStateFromProps puede restablecer cualquier parte del estado, ¡pero parece un poco defectuoso en este momento (v16.7) !, vea el enlace de arriba para el uso


componentWillReceiveProps está en desuso porque su uso "a menudo genera errores e inconsistencias".

Si algo cambia desde el exterior, considere restablecer el componente secundario por completo con la key .

Proporcionar una key apoyo al componente secundario asegura que siempre que el valor de la key cambie desde el exterior, este componente se vuelva a representar. P.ej,

componentDidUpdate(prevProps, prevState, snapshot)

Sobre su rendimiento:

Si bien esto puede sonar lento, la diferencia de rendimiento suele ser insignificante. El uso de una clave puede incluso ser más rápido si los componentes tienen una lógica pesada que se ejecuta en las actualizaciones, ya que las diferencias se omiten para ese subárbol.