Wann wird die React-Methode "componentDidUpdate" verwendet?

108

Ich habe Dutzende von ReactDateien geschrieben, benutze nie die componentDidUpdateMethode.

Gibt es ein typisches Beispiel dafür, wann diese Methode angewendet werden muss?

Ich möchte ein Beispiel aus der Praxis, keine einfache Demo.

Danke für die Antwort!

Diashowp2
quelle
Ein einfacher Fall, wenn Sie den Anfangszustand der Komponente beim Laden festlegen möchten.
Rajesh
@ Rajesh Kannst du es erklären oder mir ein Beispiel geben? Vielen Dank!
Slideshowp2
1
Ich denke, der häufigste Anwendungsfall ist, wenn Sie andere Bibliotheken (jQuery, D3 ...) haben, die direkt auf dem DOM arbeiten, zusammen mit React. Wenn die andere Bibliothek in solchen Szenarien DOM-Transformationen durchführen muss, sollten Sie componentDidUpdate verwenden, um sicherzustellen, dass das Schatten-DOM von React in das reale DOM geleert wurde.
Jorge
1
Um auf @ Jorges Kommentar einzugehen: Ich denke, der häufigste Fall wäre, nach der Aktualisierung von React aus dem realen DOM zu lesen. Zum Beispiel, wenn Sie die genauen Abmessungen von DOM-Elementen oder die Position von DOM-Elementen im Ansichtsfenster kennen möchten. ZB für Animationen oder Übergänge, auf deren Verwaltung Sie reagieren möchten. Ich würde definitiv davon abraten, jQuery zum Ändern des DOM zu verwenden, nachdem die Reaktion gerendert wurde. Es ist eine schlechte Idee, wenn + eine andere Bibliothek dasselbe DOM ändert.
Winter

Antworten:

88

Ein einfaches Beispiel wäre eine App, die Eingabedaten vom Benutzer sammelt und diese Daten dann mit Ajax in eine Datenbank hochlädt. Hier ist ein vereinfachtes Beispiel (nicht ausgeführt - möglicherweise Syntaxfehler):

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

Wenn sich also die Komponente stateändert, werden die Daten automatisch gespeichert. Es gibt auch andere Möglichkeiten, dies zu implementieren. Dies componentDidUpdateist besonders nützlich, wenn ein Vorgang ausgeführt werden muss, nachdem das DOM aktualisiert und die Aktualisierungswarteschlange geleert wurde. Es ist wahrscheinlich am nützlichsten auf komplexe rendersund stateoder DOM ändert oder wenn Sie etwas brauchen , das zu sein , absolut ausgeführt letzte Sache werden.

Das obige Beispiel ist zwar recht einfach, beweist aber wahrscheinlich den Punkt. Eine Verbesserung könnte darin bestehen, die Häufigkeit zu begrenzen, mit der die automatische Speicherung ausgeführt werden kann (z. B. maximal alle 10 Sekunden), da sie derzeit bei jedem Tastendruck ausgeführt wird.

Ich habe auch eine Demo zu dieser Geige gemacht, um sie zu demonstrieren.


Weitere Informationen finden Sie in den offiziellen Dokumenten :

componentDidUpdate()wird sofort nach der Aktualisierung aufgerufen. Diese Methode wird beim ersten Rendern nicht aufgerufen.

Nutzen Sie dies als Gelegenheit, um das DOM zu bearbeiten, wenn die Komponente aktualisiert wurde. Dies ist auch ein guter Ort, um Netzwerkanforderungen auszuführen, solange Sie die aktuellen Requisiten mit früheren Requisiten vergleichen (z. B. ist eine Netzwerkanforderung möglicherweise nicht erforderlich, wenn sich die Requisiten nicht geändert haben).

Chris
quelle
Ich denke this.setState({...}, callback), callbackgleich _commitAutoSave, was denkst du? Also, ich denke, dieser Fall kann eine componentDidUpdateMethode verwenden, muss es aber nicht, oder? Geige
Diashowp2
1
Ja, Sie könnten einen Rückruf verwenden, das Problem wird jedoch schwieriger, wenn mehrere setStates nacheinander ausgeführt werden.
Chris
Danke für deine Antwort. Ein zu verwendender Fall componentDidUpdateist also, mehrere setStates zu lösen! Irgendwelche anderen Ideen?
Slideshowp2
@novaline Ich sehe, dass sie es in der React-Sound-Komponente github.com/leoasis/react-sound/blob/master/src/index.js verwenden . Ich bin mir nicht ganz sicher, warum sie es verwenden, aber ich dachte, ich Ich würde den Link teilen, damit Sie einen Blick darauf werfen können.
Sarah
3
Dies ist ein gutes Beispiel, aber es fehlt eine wichtige Empfehlung in den React-Dokumenten. "Dies ist auch ein guter Ort, um Netzwerkanforderungen zu erfüllen, solange Sie die aktuellen Requisiten mit früheren Requisiten vergleichen (z. B. ist eine Netzwerkanforderung möglicherweise nicht erforderlich, wenn sich die Requisiten nicht geändert haben)." reactjs.org/docs/react-component.html#componentdidupdate Ebenso sollte der Aufruf bei jedem Aufruf der setStateCDU in bedingte Logik eingeschlossen werden .
theUtherSide
5

Manchmal können Sie einen Statuswert von Requisiten im Konstruktor oder in componentDidMount hinzufügen. Möglicherweise müssen Sie setState aufrufen, wenn sich die Requisiten geändert haben, die Komponente jedoch bereits bereitgestellt wurde, sodass componentDidMount nicht ausgeführt wird und der Konstruktor auch nicht ausgeführt wird. In diesem speziellen Fall können Sie componentDidUpdate verwenden, da sich die Requisiten geändert haben. Sie können setState in componentDidUpdate mit neuen Requisiten aufrufen.

Hasan Ahmed
quelle
2

Ich habe componentDidUpdate()in Highchart verwendet.

Hier ist ein einfaches Beispiel für diese Komponente.

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' }} />;
  }
}
Asad Link
quelle
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
quelle
1

Diese Lebenszyklusmethode wird aufgerufen, sobald die Aktualisierung erfolgt. Der häufigste Anwendungsfall für die componentDidUpdate () -Methode ist das Aktualisieren des DOM als Reaktion auf Prop- oder Statusänderungen.

Sie können setState () in diesem Lebenszyklus aufrufen. Beachten Sie jedoch, dass Sie es in einen Zustand einschließen müssen, um nach Status- oder Requisitenänderungen gegenüber dem vorherigen Status zu suchen. Eine falsche Verwendung von setState () kann zu einer Endlosschleife führen. Schauen Sie sich das folgende Beispiel an, das ein typisches Anwendungsbeispiel für diese Lebenszyklusmethode zeigt.

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

Beachten Sie im obigen Beispiel, dass wir die aktuellen Requisiten mit den vorherigen Requisiten vergleichen. Hiermit wird überprüft, ob sich die Requisiten gegenüber dem aktuellen Stand geändert haben. In diesem Fall muss der API-Aufruf nicht ausgeführt werden, wenn sich die Requisiten nicht geändert haben.

Weitere Informationen finden Sie in den offiziellen Dokumenten:

Kashif
quelle
Was tun bei this.fetchData is not a function?
Tomrlh
Morgen ist es ein Funktionsaufruf
Kashif
0

Wenn sich etwas im Status geändert hat und Sie einen Nebeneffekt aufrufen müssen (z. B. eine Aufforderung zum Abrufen, Setzen, Veröffentlichen, Löschen). Sie müssen also anrufen, componentDidUpdate()da componentDidMount()bereits angerufen wird.

Nachdem Sie den Nebeneffekt in componentDidUpdate () aufgerufen haben, können Sie den Status basierend auf den Antwortdaten in der Datei auf einen neuen Wert setzen then((response) => this.setState({newValue: "here"})). Stellen Sie sicher, dass Sie die Endlosschleife überprüfen prevPropsoder prevStatevermeiden müssen, da beim Setzen des Status auf einen neuen Wert die KomponenteDidUpdate () erneut aufgerufen wird.

Es gibt zwei Stellen, an denen ein Nebeneffekt für bewährte Verfahren aufgerufen werden kann: componentDidMount () und componentDidUpdate ()

K.tin
quelle