Fehlerbehandlung

Die error.js-Dateikonvention ermöglicht die elegante Behandlung unerwarteter Laufzeitfehler in verschachtelten Routen.

  • Automatisches Umschließen eines Routensegments und seiner verschachtelten Kinder in einer React Error Boundary.
  • Erstellung einer spezifischen Fehler-UI für bestimmte Segmente mithilfe der Dateisystemhierarchie zur Granularitätsanpassung.
  • Isolierung von Fehlern auf betroffene Segmente bei gleichzeitiger Funktionalität des restlichen Anwendung.
  • Hinzufügen von Funktionen zur Fehlerbehebung ohne vollständigen Seitenneuladung.

Erstellen Sie eine Fehler-UI, indem Sie eine error.js-Datei in einem Routensegment anlegen und eine React-Komponente exportieren:

error.js special file
'use client' // Fehlerkomponenten müssen Client Components sein

import { useEffect } from 'react'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    // Fehler an einen Error Reporting Service senden
    console.error(error)
  }, [error])

  return (
    <div>
      <h2>Etwas ist schiefgelaufen!</h2>
      <button
        onClick={
          // Versuch der Wiederherstellung durch erneutes Rendern des Segments
          () => reset()
        }
      >
        Erneut versuchen
      </button>
    </div>
  )
}
'use client' // Fehlerkomponenten müssen Client Components sein

import { useEffect } from 'react'

export default function Error({ error, reset }) {
  useEffect(() => {
    // Fehler an einen Error Reporting Service senden
    console.error(error)
  }, [error])

  return (
    <div>
      <h2>Etwas ist schiefgelaufen!</h2>
      <button
        onClick={
          // Versuch der Wiederherstellung durch erneutes Rendern des Segments
          () => reset()
        }
      >
        Erneut versuchen
      </button>
    </div>
  )
}

Funktionsweise von error.js

How error.js works
  • error.js erstellt automatisch eine React Error Boundary, die ein verschachteltes Kindsegment oder eine page.js-Komponente umschließt.
  • Die aus error.js exportierte React-Komponente dient als Fallback-Komponente.
  • Wenn innerhalb der Error Boundary ein Fehler auftritt, wird dieser eingegrenzt und die Fallback-Komponente gerendert.
  • Während die Fallback-Fehlerkomponente aktiv ist, behalten Layouts oberhalb der Error Boundary ihren Zustand bei und bleiben interaktiv, und die Fehlerkomponente kann Funktionen zur Fehlerbehebung anzeigen.

Wiederherstellung nach Fehlern

Die Ursache eines Fehlers kann manchmal temporär sein. In diesen Fällen kann ein einfacher erneuter Versuch das Problem lösen.

Eine Fehlerkomponente kann die reset()-Funktion verwenden, um den Benutzer zur Fehlerbehebung aufzufordern. Bei Ausführung versucht die Funktion, den Inhalt der Error Boundary erneut zu rendern. Bei Erfolg wird die Fallback-Fehlerkomponente durch das Ergebnis des erneuten Renderings ersetzt.

'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div>
      <h2>Etwas ist schiefgelaufen!</h2>
      <button onClick={() => reset()}>Erneut versuchen</button>
    </div>
  )
}
'use client'

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Etwas ist schiefgelaufen!</h2>
      <button onClick={() => reset()}>Erneut versuchen</button>
    </div>
  )
}

Verschachtelte Routen

React-Komponenten, die durch spezielle Dateien erstellt werden, werden in einer spezifischen verschachtelten Hierarchie gerendert.

Beispielsweise wird eine verschachtelte Route mit zwei Segmenten, die beide layout.js- und error.js-Dateien enthalten, in der folgenden vereinfachten Komponentenhierarchie gerendert:

Nested Error Component Hierarchy

Die verschachtelte Komponentenhierarchie hat Auswirkungen auf das Verhalten von error.js-Dateien in einer verschachtelten Route:

  • Fehler steigen zur nächstgelegenen übergeordneten Error Boundary auf. Das bedeutet, dass eine error.js-Datei Fehler für alle ihre verschachtelten Kindsegmente behandelt. Mehr oder weniger granulare Fehler-UI kann durch Platzieren von error.js-Dateien auf verschiedenen Ebenen in den verschachtelten Ordnern einer Route erreicht werden.
  • Eine error.js-Boundary behandelt keine Fehler, die in einer layout.js-Komponente im selben Segment ausgelöst werden, da die Error Boundary innerhalb dieser Layout-Komponente verschachtelt ist.

Fehlerbehandlung in Layouts

error.js-Boundaries fangen keine Fehler ab, die in layout.js- oder template.js-Komponenten des selben Segments auftreten. Diese beabsichtigte Hierarchie stellt sicher, dass wichtige UI-Elemente, die zwischen Geschwisterrouten geteilt werden (wie Navigation), bei einem Fehler sichtbar und funktionsfähig bleiben.

Um Fehler innerhalb eines bestimmten Layouts oder Templates zu behandeln, platzieren Sie eine error.js-Datei im übergeordneten Segment des Layouts.

Um Fehler innerhalb des Root-Layouts oder -Templates zu behandeln, verwenden Sie eine Variante von error.js namens global-error.js.

Fehlerbehandlung in Root-Layouts

Die Root-app/error.js-Boundary fängt keine Fehler ab, die in der Root-app/layout.js- oder app/template.js-Komponente auftreten.

Um speziell Fehler in diesen Root-Komponenten zu behandeln, verwenden Sie eine Variante von error.js namens app/global-error.js im Root-app-Verzeichnis.

Im Gegensatz zur Root-error.js umschließt die global-error.js-Boundary die gesamte Anwendung, und ihre Fallback-Komponente ersetzt das Root-Layout, wenn sie aktiv ist. Daher ist es wichtig zu beachten, dass global-error.js eigene <html>- und <body>-Tags definieren muss.

global-error.js ist die am wenigsten granulare Fehler-UI und kann als "Catch-all"-Fehlerbehandlung für die gesamte Anwendung betrachtet werden. Es ist unwahrscheinlich, dass sie häufig ausgelöst wird, da Root-Komponenten typischerweise weniger dynamisch sind und andere error.js-Boundaries die meisten Fehler abfangen.

Auch wenn eine global-error.js definiert ist, wird dennoch empfohlen, eine Root-error.js zu definieren, deren Fallback-Komponente innerhalb des Root-Layouts gerendert wird, das global geteilte UI und Branding enthält.

'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <html>
      <body>
        <h2>Etwas ist schiefgelaufen!</h2>
        <button onClick={() => reset()}>Erneut versuchen</button>
      </body>
    </html>
  )
}
'use client'

export default function GlobalError({ error, reset }) {
  return (
    <html>
      <body>
        <h2>Etwas ist schiefgelaufen!</h2>
        <button onClick={() => reset()}>Erneut versuchen</button>
      </body>
    </html>
  )
}

Behandlung von Server-Fehlern

Wenn ein Fehler in einer Server-Komponente auftritt, leitet Next.js ein Error-Objekt (in Produktionsumgebungen ohne sensible Fehlerinformationen) an die nächstgelegene error.js-Datei als error-Prop weiter.

Absichern sensibler Fehlerinformationen

In Produktionsumgebungen enthält das an den Client weitergeleitete Error-Objekt nur eine generische message- und digest-Eigenschaft.

Dies ist eine Sicherheitsmaßnahme, um das versehentliche Offenlegen potenziell sensibler Details im Fehler an den Client zu vermeiden.

Die message-Eigenschaft enthält eine generische Nachricht über den Fehler, und die digest-Eigenschaft enthält einen automatisch generierten Hash des Fehlers, der zum Abgleich mit dem entsprechenden Fehler in serverseitigen Logs verwendet werden kann.

Während der Entwicklung wird das an den Client weitergeleitete Error-Objekt serialisiert und enthält die message des ursprünglichen Fehlers zur einfacheren Fehlersuche.