Quand utiliser la méthode React «componentDidUpdate»?

110

J'ai écrit des dizaines de Reactfichiers, n'utilisez jamais de componentDidUpdateméthode.

Existe-t-il un exemple typique de besoin d'utiliser cette méthode?

Je veux un exemple concret, pas une simple démo.

Merci d'avoir répondu!

diaporamap2
la source
Un cas simple où vous souhaitez définir l'état initial du composant en charge.
Rajesh
@Rajesh Pouvez-vous l'expliquer ou me donner un exemple? Merci!
diaporamap2
1
Je pense que le cas d'utilisation le plus courant est lorsque vous avez d'autres bibliothèques (jQuery, D3 ...) qui fonctionnent directement sur le DOM, couplées avec React. Dans de tels scénarios, si l'autre bibliothèque doit effectuer des transformations DOM, vous devez utiliser componentDidUpdate pour vous assurer que le shadow DOM de React a été vidé dans le vrai DOM.
Jorge
1
Pour élaborer sur le commentaire de @ Jorge: je pense que le cas le plus courant serait de LIRE à partir du vrai DOM après la mise à jour de React. Par exemple, lorsque vous souhaitez connaître les dimensions exactes des éléments DOM, ou la position des éléments DOM dans la fenêtre. Par exemple, pour les animations ou les transitions que vous souhaitez gérer. Je déconseillerais définitivement d'utiliser jQuery pour changer le DOM après le rendu de react. Avoir réagi + une autre bibliothèque changer le même morceau de DOM est une mauvaise idée.
wintvelt

Réponses:

90

Un exemple simple serait une application qui collecte les données d'entrée de l'utilisateur, puis utilise Ajax pour télécharger lesdites données dans une base de données. Voici un exemple simplifié (je ne l'ai pas exécuté - peut avoir des erreurs de syntaxe):

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

Ainsi, chaque fois que le composant a un statechangement, il enregistre automatiquement les données. Il existe également d'autres moyens de le mettre en œuvre. Le componentDidUpdateest particulièrement utile lorsqu'une opération doit avoir lieu après la mise à jour du DOM et la mise à jour de la file d'attente. Il est probablement plus utile sur des questions complexes renderset stateou change DOM ou lorsque vous avez besoin de quoi être la absolument dernière chose à exécuter.

L'exemple ci-dessus est cependant assez simple, mais prouve probablement le point. Une amélioration pourrait être de limiter le nombre de fois que la sauvegarde automatique peut s'exécuter (par exemple, au maximum toutes les 10 secondes) car pour le moment, elle s'exécutera à chaque frappe de touche.

J'ai également fait une démo sur ce violon pour le démontrer.


Pour plus d'informations, reportez-vous à la documentation officielle :

componentDidUpdate()est appelée immédiatement après la mise à jour. Cette méthode n'est pas appelée pour le rendu initial.

Profitez-en pour opérer sur le DOM lorsque le composant a été mis à jour. C'est aussi un bon endroit pour faire des requêtes réseau tant que vous comparez les props actuels aux props précédents (par exemple, une demande réseau peut ne pas être nécessaire si les props n'ont pas changé).

Chris
la source
Je pense this.setState({...}, callback), l' callbackégal _commitAutoSave, que pensez-vous? Donc, je pense que ce cas peut utiliser la componentDidUpdateméthode, mais pas le doit, ai-je raison? fiddle
diaporamap2
1
Oui, vous pouvez utiliser un rappel, mais le problème devient plus délicat quand / s'il y a plusieurs setStates qui sont exécutés successivement.
Chris
Merci pour votre réponse. Donc, un cas à utiliser componentDidUpdateest de résoudre plusieurs setStates! D'autres idées?
diaporamap2
@novaline Je vois qu'ils l'utilisent dans le composant react -sound github.com/leoasis/react-sound/blob/master/src/index.js .. Je ne sais pas exactement pourquoi ils l'utilisent mais je pensais que je Je partagerais le lien pour que vous puissiez y jeter un œil.
Sarah
3
C'est un bon exemple, mais il manque une recommandation clé de la documentation React. "C'est aussi un bon endroit pour faire des requêtes réseau tant que vous comparez les props actuels aux props précédents (par exemple, une demande réseau peut ne pas être nécessaire si les props n'ont pas changé)." reactjs.org/docs/react-component.html#componentdidupdate De même, on devrait envelopper l'appel en logique conditionnelle à chaque appel setStateen CDU.
theUtherSide
5

Parfois, vous pouvez ajouter une valeur d'état à partir des accessoires dans le constructeur ou dans componentDidMount, vous devrez peut-être appeler setState lorsque les accessoires ont changé mais que le composant a déjà été monté, donc componentDidMount ne s'exécutera pas et le constructeur non plus; dans ce cas particulier, vous pouvez utiliser componentDidUpdate puisque les props ont changé, vous pouvez appeler setState dans componentDidUpdate avec de nouveaux props.

Hasan Ahmed
la source
2

J'ai utilisé componentDidUpdate()dans highchart.

Voici un exemple simple de ce composant.

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' }} />;
  }
}
Lien Asad
la source
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));

    }
}
James Siva
la source
1

Cette méthode de cycle de vie est appelée dès la mise à jour. Le cas d'utilisation le plus courant de la méthode componentDidUpdate () est la mise à jour du DOM en réponse aux changements de prop ou d'état.

Vous pouvez appeler setState () dans ce cycle de vie, mais gardez à l'esprit que vous devrez l'envelopper dans une condition pour vérifier les changements d'état ou de prop par rapport à l'état précédent. Une utilisation incorrecte de setState () peut conduire à une boucle infinie. Jetez un œil à l'exemple ci-dessous qui montre un exemple d'utilisation typique de cette méthode de cycle de vie.

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

Notez dans l'exemple ci-dessus que nous comparons les accessoires actuels aux accessoires précédents. Ceci permet de vérifier s'il y a eu un changement dans les accessoires par rapport à ce qu'ils sont actuellement. Dans ce cas, il ne sera pas nécessaire de faire l'appel d'API si les accessoires n'ont pas changé.

Pour plus d'informations, reportez-vous à la documentation officielle:

Kashif
la source
Que faire en cas de this.fetchData is not a function?
tomrlh
tomrlh c'est un appel de fonction
Kashif
0

Quand quelque chose dans l'état a changé et que vous devez appeler un effet secondaire (comme une demande à api - obtenir, mettre, publier, supprimer). Vous devez donc appeler componentDidUpdate()car il componentDidMount()est déjà appelé.

Après avoir appelé effet secondaire dans componentDidUpdate (), vous pouvez définir l'état sur une nouvelle valeur en fonction des données de réponse dans le then((response) => this.setState({newValue: "here"})). Veuillez vous assurer que vous devez vérifier prevPropsou prevStateéviter une boucle infinie car lors de la définition de l'état sur une nouvelle valeur, le composantDidUpdate () appellera à nouveau.

Il y a 2 endroits pour appeler un effet secondaire pour les meilleures pratiques - componentDidMount () et componentDidUpdate ()

K. étain
la source