Quando utilizzare il metodo "componentDidUpdate" di React?


109

Ho scritto dozzine di Reactfile, non uso mai il componentDidUpdatemetodo.

C'è qualche tipico esempio di quando è necessario utilizzare questo metodo?

Voglio qualche esempio del mondo reale, non una semplice demo.

Grazie per la risposta!



Un semplice caso in cui si desidera impostare lo stato iniziale del componente al caricamento.
Rajesh

@Rajesh Puoi spiegarmi o farmi un esempio? Grazie!
slideshowp2

1
Penso che il caso d'uso più comune sia quando hai altre librerie (jQuery, D3 ...) che funzionano direttamente sul DOM, accoppiate con React. In tali scenari, se l'altra libreria ha bisogno di eseguire trasformazioni DOM, dovresti usare componentDidUpdate per assicurarti che lo shadow DOM di React sia stato scaricato nel DOM reale.
Jorge

1
Per approfondire il commento di @ Jorge: penso che il caso più comune sarebbe LEGGERE dal vero DOM dopo che React ha aggiornato. Ad esempio, quando si desidera conoscere le dimensioni esatte degli elementi DOM o la posizione degli elementi DOM nella finestra. Ad esempio, per animazioni o transizioni che vuoi gestire con la reazione. Vorrei assolutamente sconsigliare l'uso di jQuery per modificare il DOM dopo il rendering di react. Avere reagito + un'altra libreria che cambia lo stesso pezzo di DOM è una cattiva idea.
wintvelt

Risposte:


89

Un semplice esempio potrebbe essere un'app che raccoglie i dati di input dall'utente e quindi utilizza Ajax per caricare tali dati su un database. Ecco un esempio semplificato (non l'ho eseguito - potrebbero esserci errori di sintassi):

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

Pertanto, ogni volta che il componente ha una statemodifica, salva automaticamente i dati. Ci sono anche altri modi per implementarlo. Il componentDidUpdateè particolarmente utile quando un'operazione deve avvenire dopo il DOM è aggiornata e la coda di aggiornamento è svuotata. Probabilmente è più utile su modifiche complesse renderse / stateo DOM o quando hai bisogno che qualcosa sia assolutamente l' ultima cosa da eseguire.

L'esempio sopra è piuttosto semplice, ma probabilmente dimostra il punto. Un miglioramento potrebbe essere quello di limitare il numero di volte che il salvataggio automatico può essere eseguito (es. Max ogni 10 secondi) perché in questo momento verrà eseguito a ogni pressione di un tasto.

Ho fatto anche una demo su questo violino per dimostrarlo.


Per maggiori informazioni, fare riferimento ai documenti ufficiali :

componentDidUpdate()viene richiamato immediatamente dopo l'aggiornamento. Questo metodo non viene chiamato per il rendering iniziale.

Usalo come un'opportunità per operare sul DOM quando il componente è stato aggiornato. Questo è anche un buon posto per fare richieste di rete fintanto che si confrontano gli oggetti di scena correnti con quelli precedenti (ad esempio una richiesta di rete potrebbe non essere necessaria se gli oggetti di scena non sono cambiati).


Penso this.setState({...}, callback), callbackuguale _commitAutoSave, cosa ne pensi? Quindi, penso che questo caso possa usare il componentDidUpdatemetodo, ma non il dovere, giusto? violino
slideshowp2

1
Sì, potresti usare una richiamata, tuttavia il problema diventa più complicato quando / se ci sono più setState che vengono eseguiti in successione.
Chris il

Grazie per la tua risposta. Quindi, un caso da usare componentDidUpdateè risolvere più setState! Altre idee?
slideshowp2

@novaline vedo che lo usano nel componente react-sound github.com/leoasis/react-sound/blob/master/src/index.js .. Non sono esattamente sicuro del motivo per cui lo stanno usando ma pensavo di sì condividerei il link per farti dare un'occhiata.
Sarah

3
Questo è un buon esempio, ma manca una raccomandazione chiave dai documenti di React. "Questo è anche un buon posto per fare richieste di rete purché si confrontino gli oggetti di scena correnti con quelli precedenti (ad esempio una richiesta di rete potrebbe non essere necessaria se gli oggetti di scena non sono cambiati)." reactjs.org/docs/react-component.html#componentdidupdate Allo stesso modo, si dovrebbe racchiudere la chiamata in logica condizionale ogni volta che si chiama setStatein CDU.
theUtherSide

5

A volte potresti aggiungere un valore di stato da props in constructor o componentDidMount, potresti dover chiamare setState quando le props sono cambiate ma il componente è già montato, quindi componentDidMount non verrà eseguito e nemmeno il costruttore; in questo caso particolare, puoi usare componentDidUpdate poiché gli oggetti di scena sono cambiati, puoi chiamare setState in componentDidUpdate con nuovi oggetti di scena.


2

L'ho usato componentDidUpdate()in highchart.

Ecco un semplice esempio di questo 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

Questo metodo del ciclo di vita viene richiamato non appena viene eseguito l'aggiornamento. Il caso d'uso più comune per il metodo componentDidUpdate () è l'aggiornamento del DOM in risposta a modifiche di prop o stato.

Puoi chiamare setState () in questo ciclo di vita, ma tieni presente che dovrai racchiuderlo in una condizione per verificare lo stato o le modifiche dell'elica dallo stato precedente. L'utilizzo errato di setState () può portare a un ciclo infinito. Dai un'occhiata all'esempio di seguito che mostra un tipico esempio di utilizzo di questo metodo del ciclo di vita.

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

Si noti nell'esempio precedente che stiamo confrontando gli oggetti di scena attuali con quelli precedenti. Questo serve per verificare se c'è stato un cambiamento negli oggetti di scena rispetto a quello che è attualmente. In questo caso, non sarà necessario effettuare la chiamata API se gli oggetti di scena non sono cambiati.

Per maggiori informazioni, fare riferimento ai documenti ufficiali:


Cosa fare in caso di this.fetchData is not a function?
tomrlh

tomrlh è una chiamata di funzione
Kashif

0

Quando qualcosa nello stato è cambiato e devi chiamare un effetto collaterale (come una richiesta all'API - get, put, post, delete). Quindi devi chiamare componentDidUpdate()perché componentDidMount()è già chiamato.

Dopo aver chiamato l'effetto collaterale in componentDidUpdate (), è possibile impostare lo stato su un nuovo valore in base ai dati di risposta nel file then((response) => this.setState({newValue: "here"})). Assicurati di controllare prevPropso prevStatedi evitare un ciclo infinito perché quando imposti lo stato su un nuovo valore, componentDidUpdate () chiamerà di nuovo.

Esistono 2 posizioni per chiamare un effetto collaterale per la migliore pratica: componentDidMount () e componentDidUpdate ()

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.