Pregunta Estado de actualización en cambio de accesorios en formulario de reacción


Estoy teniendo problemas con un formulario Reaccionar y administrar el estado correctamente. Tengo un campo de entrada de tiempo en una forma (en un modal). El valor inicial se establece como una variable de estado en getInitialStatey se transfiere 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 forma, el valor predeterminado start_time nunca cambia, ya que solo se define una vez en getInitialState.

He intentado usar componentWillUpdate 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

75
2017-09-05 14:39


origen


Respuestas:


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

Reaccionar tiene algunos consejos sobre cómo lidiar con este escenario. (Tenga en cuenta que este es un artículo antiguo que se eliminó de la web. Aquí hay un enlace al doc en accesorios de componentes)

Usar accesorios para generar estado en getInitialState a menudo conduce a la duplicación de la "fuente de la verdad", es decir, dónde están los datos reales. Esto es porque 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 padres props a un niño state el método de renderizado no siempre se llama en la actualización de prop. Tienes que invocarlo manualmente, usando el componentWillReceiveProps método.

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

180
2017-09-05 15:29



Aparentemente las cosas están cambiando ... getDerivedStateFromProps () ahora es 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 de arriba por danburzo @ github)


15
2018-04-17 01:02



También hay componentDidUpdate disponible.

Signatur de función:

componentDidUpdate(prevProps, prevState, snapshot)

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

Ver Probablemente no necesites un estado derivado Artículo, que describe Anti-Pattern para ambos componentDidUpdate y getDerivedStateFromProps. Lo encontré muy útil.


1
2017-07-08 07:47