Was ist der Unterschied zwischen getDerivedStateFromError und componentDidCatch

Lesezeit: 6 Minuten

Benutzeravatar von Tomasz Mularczyk
Tomasz Mularczyk

Was ich verstanden habe hier:

componentDidCatch:

  • wird immer im Browser aufgerufen
  • wird während der “Commit-Phase” aufgerufen, wenn das DOM bereits aktualisiert wurde
  • sollte für so etwas wie das Melden von Fehlern verwendet werden

getDerivedStateFromError:

  • wird auch beim serverseitigen Rendern aufgerufen
  • wird in der “Renderphase” aufgerufen, wenn das DOM noch nicht aktualisiert wurde
  • sollte zum Rendern einer Fallback-Benutzeroberfläche verwendet werden

Trotzdem bin ich etwas verwirrt über einige Dinge:

  1. Fangen sie beide die gleiche Art von Fehlern? oder wird jeder Lebenszyklus den anderen Fehler abfangen?
  2. sollte ich immer beide verwenden (möglicherweise in derselben “fehlerfangenden” Komponente)?
  3. „Die Verwendung von „componentDidCatch“ zur Fehlerbehebung ist nicht optimal, da es die Fallback-Benutzeroberfläche dazu zwingt, immer synchron zu rendern.“ was stimmt damit nicht?

Benutzeravatar von Estus Flask
Estus-Kolben

Die Aussagen in der Frage sind größtenteils richtig. Derzeit werden Fehlergrenzen in SSR nicht unterstützt, getDerivedStateFromError und componentDidCatch wirken sich nicht auf die Serverseite aus.

Fangen sie beide die gleiche Art von Fehlern? oder wird jeder Lebenszyklus den anderen Fehler abfangen?

Sie fangen dieselben Fehler ab, aber in unterschiedlichen Phasen. Dies war bisher mit möglich componentDidCatch allein:

  static getDerivedStateFromError() {
    return { hasError: true };
  }

und

  componentDidCatch() {
    this.setState({ hasError: true });
  }

mach das selbe, componentDidCatch hat keine Chance, serverseitig unterstützt zu werden, bis die Unterstützung für asynchrones Rendering hinzugefügt wird ReactDOMServer.

sollte ich immer beide verwenden (möglicherweise in derselben “fehlerfangenden” Komponente)?

Du kann verwende beide. Ein Beispiel aus die Dokumentation zeigt, dass:

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logComponentStackToMyService(info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

In diesem Fall werden die Verantwortlichkeiten zwischen ihnen aufgeteilt. getDerivedStateFromError tut das einzige, wofür es gut ist, dh aktualisiert den Zustand, wenn ein Fehler auftritt, während componentDidCatch bietet Nebenwirkungen und kann zugreifen this Komponenteninstanz, falls erforderlich.

“Die Verwendung von componentDidCatch zur Fehlerbehebung ist nicht optimal, da die Fallback-Benutzeroberfläche gezwungen wird, immer synchron zu rendern.” Was ist daran falsch?

Neue React-Releases zielen auf asynchrones Rendering ab, das effizienter ist. Wie auch schon erwähnt in der Kommentarist das synchrone Rendering kein großes Problem für die Fallback-Benutzeroberfläche, da dies als Randfall betrachtet werden kann.

  • Nett! könnten Sie mir auch den 3. Punkt einer gerade hinzugefügten Frage erklären?

    – Tomasz Mularczyk

    24. Oktober 2018 um 7:32 Uhr

  • Sicher. Antwort aktualisiert.

    – Estus-Kolben

    24. Oktober 2018 um 7:35 Uhr

  • Ein Teil der Informationen in OP ist falsch (ebenso wie die Informationen im Reddit-Thread, auf den es verweist). getDerivedStateFromError wird NICHT während des serverseitigen Renderns aufgerufen. Ich habe dies sowohl in React 16.4 als auch in 16.7 getestet. Reagieren Sie auf Dokumente Reactjs.org/docs/error-boundaries.html state “Fehlergrenzen fangen keine Fehler ab für… serverseitiges Rendern”

    – Motel übersehen

    6. Januar 2019 um 11:10 Uhr

  • npmjs.com/package/react-ssr-error-boundary ist ein Workaround, der dafür sorgt, dass Fehlergrenzen auf dem Server funktionieren, der verwendet werden kann, bis der neue React Async-Renderer später in diesem Jahr erscheint.

    – Motel übersehen

    7. Januar 2019 um 12:11 Uhr

  • Bedeutet das, wenn ich eine Toastnachricht über die vorhandene Benutzeroberfläche anzeigen möchte, sagen Sie “keine Netzwerkverbindung”, könnte ich einfach verwenden componentDidCatch?

    – Jonathan

    11. Januar 2021 um 12:57 Uhr

Benutzeravatar von Shubham Khatri
Shubham Khatri

Diese beiden Methoden werden aufgerufen, wenn während des Renderns, in einer Lebenszyklusmethode oder im Konstruktor einer untergeordneten Komponente ein Fehler auftritt. Sie können beim Implementieren von Fehlergrenzen verwendet werden

Laut dem Reagieren Sie auf Dokumente

getDerivedStateFromError lifecycle wird aufgerufen, nachdem eine untergeordnete Komponente einen Fehler ausgegeben hat. Es empfängt den Fehler, der als Parameter ausgelöst wurde, und sollte einen Wert für den Aktualisierungsstatus zurückgeben.


Fangen sie beide die gleiche Art von Fehlern? oder wird jeder Lebenszyklus den anderen Fehler abfangen?

Beide Lebenszyklusmethoden fangen die gleichen Fehler ab, aber die Argumente für diese beiden Komponenten sind unterschiedlich.

Während getDerivedStateFromError erhält nur den Fehler als Argumente, componentDidCatch erhält auch den zweiten Parameter, nämlich info, i.e An object with a componentStack key containing information about which component threw the error.

getDerivedStateFromError() wird während der „Render“-Phase aufgerufen, daher sind keine Nebeneffekte zulässig. Verwenden Sie für diese Anwendungsfälle componentDidCatch() stattdessen. Während componentDidCatch kann auch für setState verwendet werden, aber dies wird in zukünftigen Versionen veraltet sein

componentDidCatch sollte für Nebeneffekte wie Protokollierungsfehler verwendet werden


Ebenfalls @Brian Vaughn hat mehr über ihre Verwendung unter dem von Ihnen bereitgestellten Link erläutert

getDerivedStateFromError arbeitet mit serverseitigem Rendering.
componentDidCatch ist ein Commit-Phasen-Lebenszyklus, aber es gibt keine Commit-Phase auf dem Server. getDerivedStateFromError ist ein Renderphasen-Lebenszyklus und kann daher verwendet werden, um die Fehlerbehandlung auf dem Server zu aktivieren.

Die Wiederherstellung der Renderphase ist sicherer. Die Geschichte zur Fehlerbehebung über
componentDidCatch ist ein wenig ruckelig, da es für alles unterhalb der fehlerhaften Komponente auf einen Zwischencommit von “null” angewiesen ist. Dies kann zu nachfolgenden Fehlern innerhalb von Komponenten weiter oben im Baum führen, die „componentDidMount“ oder „componentDidUpdate“ implementieren und einfach davon ausgehen, dass ihre Refs nicht null sind (weil sie sich immer im Nicht-Fehlerfall befinden).

getDerivedStateFromError erzwingt kein synchrones Rendern. Da Zustandsaktualisierungen aus Commit-Phasen-Lebenszyklen immer synchron sind und weil „componentDidCatch“ während der Commit-Phase aufgerufen wird, ist die Verwendung von „componentDidCatch“ für die Fehlerbehebung nicht optimal, da sie die Fallback-Benutzeroberfläche dazu zwingt, immer synchron zu rendern. (Dies ist zugegebenermaßen kein großes Problem, da die Fehlerbehebung ein Randfall sein sollte.)

Im Fehlerfall gilt Ihre Fehlergrenze
getDerivedStateFromError() -Methode wird zuerst aufgerufen (um den Status zu aktualisieren), dann die render() -Methode (um die Fallback-Benutzeroberfläche tatsächlich zu rendern) und dann componentDidCatch (sobald die Fallback-Benutzeroberfläche an das DOM übergeben wurde).

Wenn Ihre Fehlergrenze andere Lebenszyklusmethoden definiert (z. B. „componentWillUpdate“, „componentDidUpdate“), werden sie ebenfalls aufgerufen, genau wie bei jedem anderen Rendering.


“Die Verwendung von componentDidCatch zur Fehlerbehebung ist nicht optimal, da die Fallback-Benutzeroberfläche gezwungen wird, immer synchron zu rendern.” Was ist daran falsch?

Das bedeutet, dass „componentDidCatch“ nach der „render“-Methode aufgerufen wird, die die Fallback-UI rendert, was zu weiteren Problemen führen kann getDerivedStateFromError aktualisiert den Status vor der Renderphase, sodass die richtige Fallback-Benutzeroberfläche gerendert wird und keine weiteren Fehler in den gerenderten Komponenten verursacht werden. Außerdem zielen die neuen Versionen auf asynchrones Rendern ab, was mit dem aktuellen Ansatz Probleme haben könnte

  • „Die Verwendung von „componentDidCatch“ für die Fehlerbehebung ist nicht optimal, da es die Fallback-Benutzeroberfläche dazu zwingt, immer synchron zu rendern.“ Ich verstehe nicht ganz, was es bedeutet, dass es “synchron rendert”? Ich meine, was ist daran falsch?

    – Tomasz Mularczyk

    24. Oktober 2018 um 7:26 Uhr


  • @TomaszMularczyk, das bedeutet, dass componentDidCatch nach der Rendermethode aufgerufen wird, die die Fallback-UI rendert, und das kann zu weiteren Problemen führen, während getDerivedStateFromError den Status vor der Renderphase aktualisiert, sodass die richtige Fallback-UI gerendert wird und keine weiteren Fehler verursacht werden die gerenderten Komponenten. Außerdem zielen die neuen Versionen auf asynchrones Rendern ab, was mit dem aktuellen Ansatz Probleme haben könnte

    – Shubham Khatri

    24. Oktober 2018 um 7:36 Uhr


Benutzeravatar von AmerllicA
AmerllicA

Eigentlich haben beide das gleiche Ziel, aber in einer anderen Phase, definitiv, zum Schreiben ErrorBoundary Komponente, die ich verwende getDerivedStateFromError Methode, weil ich der gehorche ReactJs-Dokumentation. Das Dokument hat diesen Satz:

Statik verwenden getDerivedStateFromError() um eine Fallback-Benutzeroberfläche zu rendern, nachdem ein Fehler ausgelöst wurde. Verwenden componentDidCatch() um Fehlerinformationen zu protokollieren.

Sicherlich hat es einige Gründe, die ich immer zum Rendern der Fallback-Benutzeroberfläche verwende getDerivedStateFromError und um Informationen zu sammeln und etwas zu tun, das ich benutze componentDidCatch.

  • codepen.io/gaearon/pen/wqvxGa Ist dieses Beispiel also irgendwie falsch, da es den Zustand einstellt componentDidCatch anstatt es einzubauen getDerivedStateFromError ? Vielen Dank

    – Tonix

    29. Mai 2020 um 8:51 Uhr


1434350cookie-checkWas ist der Unterschied zwischen getDerivedStateFromError und componentDidCatch

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy