¿Cuándo usar el método React "componentDidUpdate"?


109

Escribí docenas de Reactarchivos, nunca los usocomponentDidUpdate método.

¿Existe algún ejemplo típico de cuándo es necesario utilizar este método?

Quiero un ejemplo del mundo real, no una simple demostración.

¡Gracias por la respuesta!



Un caso sencillo en el que desea establecer el estado inicial del componente en carga.
Rajesh

@Rajesh ¿Puedes explicarlo o darme un ejemplo? ¡Gracias!
slideshowp2

1
Creo que el caso de uso más común es cuando tiene otras bibliotecas (jQuery, D3 ...) que funcionan directamente en el DOM, junto con React. En tales escenarios, si la otra biblioteca necesita realizar transformaciones DOM, debe usar componentDidUpdate para asegurarse de que el DOM en la sombra de React se haya descargado en el DOM real.
Jorge

1
Para ampliar el comentario de @ Jorge: creo que el caso más común sería LEER desde el DOM real después de que React se haya actualizado. Por ejemplo, cuando desee conocer las dimensiones exactas de los elementos DOM o la posición de los elementos DOM en la ventana gráfica. Por ejemplo, para animaciones o transiciones que desee que reaccione para administrar. Definitivamente desaconsejaría el uso de jQuery para cambiar el DOM después de que reaccionó. Hacer que reaccionar + otra biblioteca cambie la misma pieza de DOM es una mala idea.
wintvelt

Respuestas:


89

Un ejemplo simple sería una aplicación que recopila datos de entrada del usuario y luego usa Ajax para cargar dichos datos en una base de datos. Aquí hay un ejemplo simplificado (no lo he ejecutado; puede tener errores de sintaxis):

export default class Task extends React.Component {
  
  constructor(props, context) {
    super(props, context);
    this.state = {
      name: "",
      age: "",
      country: ""
    };
  }

  componentDidUpdate() {
    this._commitAutoSave();
  }

  _changeName = (e) => {
    this.setState({name: e.target.value});
  }

  _changeAge = (e) => {
    this.setState({age: e.target.value});
  }

  _changeCountry = (e) => {
    this.setState({country: e.target.value});
  }

  _commitAutoSave = () => {
    Ajax.postJSON('/someAPI/json/autosave', {
      name: this.state.name,
      age: this.state.age,
      country: this.state.country
    });
  }

  render() {
    let {name, age, country} = this.state;
    return (
      <form>
        <input type="text" value={name} onChange={this._changeName} />
        <input type="text" value={age} onChange={this._changeAge} />
        <input type="text" value={country} onChange={this._changeCountry} />
      </form>
    );
  }
}

Entonces, siempre que el componente tenga un statecambio, guardará automáticamente los datos. También hay otras formas de implementarlo. El componentDidUpdatees particularmente útil cuando una operación que tiene que suceder después de que el DOM se actualiza y la cola de actualización se vacía. Probablemente sea más útil en complejos rendersystate o cambia DOM o cuando se necesita algo para ser el absoluto última cosa que debe ejecutarse.

Sin embargo, el ejemplo anterior es bastante simple, pero probablemente lo demuestra. Una mejora podría ser limitar la cantidad de veces que se puede ejecutar el guardado automático (por ejemplo, un máximo de cada 10 segundos) porque ahora se ejecutará con cada pulsación de tecla.

También hice una demostración de este violín para demostrarlo.


Para obtener más información, consulte los documentos oficiales :

componentDidUpdate()se invoca inmediatamente después de que se realiza la actualización. Este método no se llama para el renderizado inicial.

Utilice esto como una oportunidad para operar en el DOM cuando el componente se haya actualizado. Este también es un buen lugar para realizar solicitudes de red siempre que compare los accesorios actuales con los accesorios anteriores (por ejemplo, una solicitud de red puede no ser necesaria si los accesorios no han cambiado).


Yo pienso this.setState({...}, callback), callbackigual _commitAutoSave, ¿qué te parece? Entonces, creo que este caso puede usar el componentDidUpdatemétodo, pero no debe, ¿verdad? violín
slideshowp2

1
Sí, podría usar una devolución de llamada, sin embargo, el problema se vuelve más complicado cuando / si hay varios setStates que se ejecutan en sucesión.
Chris

Gracias por tu respuesta. Entonces, ¡un caso para usar componentDidUpdatees resolver múltiples setStates! ¿Alguna otra idea?
slideshowp2

@novaline Veo que lo usan en el componente react -sound github.com/leoasis/react-sound/blob/master/src/index.js .. No estoy exactamente seguro de por qué lo están usando, pero pensé que sí. Compartiría el enlace para que le eches un vistazo.
Sarah

3
Este es un buen ejemplo, pero le falta una recomendación clave de los documentos de React. "Este también es un buen lugar para realizar solicitudes de red siempre que compare los accesorios actuales con los accesorios anteriores (por ejemplo, una solicitud de red puede no ser necesaria si los accesorios no han cambiado)". reactjs.org/docs/react-component.html#componentdidupdate De manera similar, uno debe envolver la llamada en lógica condicional siempre que llame setStatea CDU.
theUtherSide

5

A veces, puede agregar un valor de estado de props en constructor o componentDidMount, es posible que deba llamar a setState cuando los props cambiaron pero el componente ya se ha montado, por lo que componentDidMount no se ejecutará y tampoco lo hará el constructor; en este caso particular, puede usar componentDidUpdate ya que los accesorios han cambiado, puede llamar a setState en componentDidUpdate con nuevos accesorios.


2

He usado componentDidUpdate() en highchart.

A continuación, se muestra un ejemplo sencillo de este componente.

import React, { PropTypes, Component } from 'react';
window.Highcharts = require('highcharts');

export default class Chartline extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      chart: ''
    };
  }

  public componentDidUpdate() {
    // console.log(this.props.candidate, 'this.props.candidate')
    if (this.props.category) {
      const category = this.props.category ? this.props.category : {};
      console.log('category', category);
      window.Highcharts.chart('jobcontainer_' + category._id, {
        title: {
          text: ''
        },
        plotOptions: {
          series: {
            cursor: 'pointer'
          }
        },
        chart: {
          defaultSeriesType: 'spline'
        },
        xAxis: {
          // categories: candidate.dateArr,
          categories: ['Day1', 'Day2', 'Day3', 'Day4', 'Day5', 'Day6', 'Day7'],
          showEmpty: true
        },
        labels: {
          style: {
            color: 'white',
            fontSize: '25px',
            fontFamily: 'SF UI Text'
          }
        },
        series: [
          {
            name: 'Low',
            color: '#9B260A',
            data: category.lowcount
          },
          {
            name: 'High',
            color: '#0E5AAB',
            data: category.highcount
          },
          {
            name: 'Average',
            color: '#12B499',
            data: category.averagecount
          }
        ]
      });
    }
  }
  public render() {
    const category = this.props.category ? this.props.category : {};
    console.log('render category', category);
    return <div id={'jobcontainer_' + category._id} style={{ maxWidth: '400px', height: '180px' }} />;
  }
}

2
componentDidUpdate(prevProps){ 

    if (this.state.authToken==null&&prevProps.authToken==null) {
      AccountKit.getCurrentAccessToken()
      .then(token => {
        if (token) {
          AccountKit.getCurrentAccount().then(account => {
            this.setState({
              authToken: token,
              loggedAccount: account
            });
          });
        } else {
          console.log("No user account logged");
        }
      })
      .catch(e => console.log("Failed to get current access token", e));

    }
}

1

Este método de ciclo de vida se invoca tan pronto como ocurre la actualización. El caso de uso más común para el método componentDidUpdate () es actualizar el DOM en respuesta a cambios de propiedad o estado.

Puede llamar a setState () en este ciclo de vida, pero tenga en cuenta que deberá ajustarlo en una condición para verificar el estado o los cambios de prop del estado anterior. El uso incorrecto de setState () puede conducir a un bucle infinito. Eche un vistazo al siguiente ejemplo que muestra un ejemplo de uso típico de este método de ciclo de vida.

componentDidUpdate(prevProps) {
 //Typical usage, don't forget to compare the props
 if (this.props.userName !== prevProps.userName) {
   this.fetchData(this.props.userName);
 }
}

Observe en el ejemplo anterior que estamos comparando los accesorios actuales con los accesorios anteriores. Esto es para verificar si ha habido un cambio en los accesorios de lo que es actualmente. En este caso, no será necesario realizar la llamada a la API si los accesorios no cambiaron.

Para obtener más información, consulte los documentos oficiales:


¿Qué hacer en caso de this.fetchData is not a function?
Tomrlh

tomrlh es una llamada de función
Kashif

0

Cuando algo en el estado ha cambiado y necesita llamar a un efecto secundario (como una solicitud a api - get, put, post, delete). Entonces necesitas llamar componentDidUpdate()porquecomponentDidMount() ya está llamado.

Después de llamar al efecto secundario en componentDidUpdate (), puede establecer el estado en un nuevo valor basado en los datos de respuesta en then((response) => this.setState({newValue: "here"})). Asegúrese de que necesita verificar prevPropsoprevState evitar un bucle infinito porque al establecer el estado en un nuevo valor, el componentDidUpdate () llamará nuevamente.

Hay 2 lugares para llamar a un efecto secundario para las mejores prácticas: componentDidMount () y componentDidUpdate ()

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.