Benutzerdefinierte Fehlerseiten in Reagieren mit GraphQL und Fehlergrenzen

GitHubs fantastische 500-Fehlerseite

Wenn dir dieser Artikel gefällt, unterstütze mich bitte, indem du Pull Reminders auscheckst, einen Slack-Bot, der deinem Team automatische Erinnerungen für GitHub-Pull-Anfragen sendet.

Eine Herausforderung, der ich kürzlich bei der Arbeit mit GraphQL und React begegnet bin, war der Umgang mit Fehlern. Als Entwickler haben wir wahrscheinlich bereits 500, 404 und 403 Seiten in von Servern gerenderten Anwendungen implementiert, aber es ist schwierig, herauszufinden, wie dies mit React und GraphQL geschehen soll.

In diesem Beitrag werde ich erläutern, wie unser Team dieses Problem angegangen ist, welche endgültige Lösung wir implementiert haben und welche interessanten Lehren aus der GraphQL-Spezifikation gezogen wurden.

Hintergrund

Das Projekt, an dem ich arbeitete, war eine ziemlich typische CRUD-App, die in React mit GraphQL, Apollo Client und Express-GraphQL erstellt wurde. Wir wollten mit bestimmten Arten von Fehlern umgehen, z. B. mit einem Serverausfall, indem wir dem Benutzer eine Standardfehlerseite anzeigen.

Unsere anfängliche Herausforderung bestand darin, herauszufinden, wie Fehler am besten an den Kunden kommuniziert werden können. GraphQL verwendet keine HTTP-Statuscodes wie 500, 400 und 403. Stattdessen enthalten die Antworten ein Fehlerarray mit einer Liste von Fehlern (weitere Informationen zu Fehlern in der GraphQL-Spezifikation).

Beispiel: So sah unsere GraphQL-Antwort aus, als auf dem Server ein Fehler auftrat:

Da GraphQL-Fehlerantworten den HTTP-Statuscode 200 zurückgeben, bestand die einzige Möglichkeit, die Art des Fehlers zu identifizieren, darin, das Fehlerarray zu untersuchen. Dies schien ein schlechter Ansatz zu sein, da die Fehlermeldungs-Eigenschaft die auf dem Server ausgelöste Ausnahme enthielt. Die GraphQL-Spezifikation gibt an, dass der Wert von message für Entwickler bestimmt ist, gibt jedoch nicht an, ob es sich bei dem Wert um eine für Menschen lesbare Nachricht oder um eine programmgesteuerte Verarbeitung handeln soll:

Jeder Fehler muss einen Eintrag mit der Schlüsselbotschaft mit einer Zeichenfolgenbeschreibung des Fehlers enthalten, damit der Entwickler den Fehler verstehen und beheben kann.

Hinzufügen von Fehlercodes zu GraphQL-Antworten

Um dieses Problem zu lösen, haben wir unseren Fehlerobjekten standardisierte Fehlercodes hinzugefügt, mit denen Clients Fehler programmgesteuert identifizieren können. Dies wurde dadurch inspiriert, dass die REST-API von Stripe zusätzlich zu von Menschen lesbaren Nachrichten auch Fehlercodes für Zeichenfolgen zurückgibt.

Wir haben uns für drei Fehlercodes entschieden: authentication_error, resource_not_found und server_error.

Um diese zu unseren GraphQL-Antworten hinzuzufügen, haben wir unsere eigene formatError-Funktion an express-graphql übergeben, die auf dem Server ausgelöste Ausnahmen Standardcodes zuordnet, die der Antwort hinzugefügt werden. Die GraphQL-Spezifikation rät im Allgemeinen vom Hinzufügen von Eigenschaften zu Fehlerobjekten ab, lässt dies jedoch zu, indem diese Einträge in ein Erweiterungsobjekt geschachtelt werden.

Unsere GraphQL-Antwortfehler waren dann einfach zu klassifizieren:

Während wir unsere eigene Methode zum Hinzufügen von Codes zu von express-graphql generierten Antworten entwickelt haben, scheint apollo-server ein ähnliches integriertes Verhalten zu bieten.

Rendern von Fehlerseiten mit React Error Boundaries

Nachdem wir herausgefunden hatten, wie wir mit Fehlern auf unserem Server umgehen können, wandten wir uns dem Kunden zu.

Standardmäßig sollte in unserer App eine globale Fehlerseite angezeigt werden (z. B. eine Seite mit der Meldung "Ups, es ist ein Fehler aufgetreten"), wenn ein Serverfehler, ein Autorisierungsfehler oder eine Autorisierung nicht gefunden wurde. Wir wollten jedoch auch die Flexibilität, um einen Fehler in einer bestimmten Komponente behandeln zu können, wenn wir wollten.

Wenn ein Benutzer beispielsweise etwas in eine Suchleiste eingibt und ein Fehler auftritt, möchten wir eine Fehlermeldung im Kontext anzeigen, anstatt auf eine Fehlerseite zu blinken.

Um dies zu erreichen, haben wir zunächst eine Komponente namens GraphqlErrorHandler erstellt, die zwischen den Abfrage- und Mutationskomponenten von apollo-client und den zu rendernden untergeordneten Elementen angeordnet ist. Diese Komponente hat in der Antwort nach Fehlercodes gesucht und eine Ausnahme ausgelöst, wenn sie einen Code identifiziert hat, der uns wichtig ist:

Um den GraphqlErrorHandler zu verwenden, haben wir die Abfrage- und Mutationskomponenten von apollo-client eingeschlossen:

Unsere Feature-Komponente hat dann unsere eigene Abfrage-Komponente verwendet, anstatt direkt auf reag-apollo zuzugreifen:

Nachdem unsere React-App Ausnahmen ausgelöst hat, als der Server Fehler zurückgab, wollten wir diese Ausnahmen behandeln und sie dem entsprechenden Verhalten zuordnen.

Denken Sie daran, dass es unser Ziel war, standardmäßig globale Fehlerseiten anzuzeigen (z. B. eine Seite mit der Meldung „Ups, etwas ist schief gelaufen“), aber dennoch die Flexibilität zu haben, einen Fehler lokal in einer beliebigen Komponente zu behandeln, wenn wir dies wünschen.

Reaktionsfehlergrenzen bieten eine fantastische Möglichkeit, dies zu tun. Fehlergrenzen sind React-Komponenten, die JavaScript-Fehler an einer beliebigen Stelle in ihrer untergeordneten Komponentenstruktur abfangen können, sodass Sie sie mit benutzerdefiniertem Verhalten behandeln können.

Wir haben eine Fehlergrenze mit dem Namen GraphqlErrorBoundary erstellt, die alle serverbezogenen Ausnahmen erfasst und die entsprechende Fehlerseite anzeigt:

Wir verwenden die Fehlergrenze als Wrapper für alle Komponenten unserer App:

Fehlergrenzen können tiefer im Komponentenbaum verwendet werden, wenn Fehler in einer Komponente behandelt werden sollen, anstatt eine Fehlerseite zu rendern.

Beispiel: So würde es aussehen, wenn wir ein benutzerdefiniertes Fehlerbehandlungsverhalten in unserer Komponente von früher wünschen:

Einpacken

GraphQL ist noch relativ neu und die Fehlerbehandlung ist eine häufige Herausforderung, der sich Entwickler scheinbar gegenübersehen. Durch die Verwendung standardisierter Fehlercodes in unseren GraphQL-Antworten können wir Kunden Fehler auf nützliche und intuitive Weise mitteilen. In unseren React-Apps bieten Fehlergrenzen eine hervorragende Möglichkeit, das Verhalten unserer App bei der Fehlerbehandlung zu standardisieren, während wir bei Bedarf dennoch flexibel sind.