"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > GlobalErrorHandler : détectez les erreurs qui tombent entre les doigts d'ErrorBoundary !

GlobalErrorHandler : détectez les erreurs qui tombent entre les doigts d'ErrorBoundary !

Publié le 2024-11-07
Parcourir:672

GlobalErrorHandler: Catch the errors that falls through ErrorBoundary

ErrorBoundary est un magnifique outil pour capturer les erreurs générées par les composants React. Vous pouvez fournir des messages d'erreur personnalisés en fonction de la nature et de l'emplacement de l'erreur elle-même. Mais toutes les erreurs générées ne sont pas gérées par ErrorBoundary ! Que fais-tu avec ça ?

Lorsque l'on considère à la fois les erreurs asynchrones et les erreurs générées depuis l'extérieur de React, le ErrorBoundary est insuffisant. Pour atténuer cela, j'ai créé dans mes applications ce que j'appelle un GlobalErrorHandler. Un composant fonctionnel qui A) affiche simplement une boîte de dialogue d'erreur, indiquant à l'utilisateur que quelque chose s'est mal passé, B) enregistre l'erreur sur le serveur, afin que nous puissions enquêter et trouver des solutions.

L'idée est simple. Nous voulons un GlobalErrorHandler à la racine de notre application. Ce gestionnaire ne doit gérer uniquement les erreurs non détectées par ErrorBoundary . De plus, l'utilisateur devrait facilement l'ignorer et nous devrions supposer que l'application est toujours utilisable.

La stratégie est donc la suivante : le GlobalErrorHandler ne fait rien du tout, sauf le rendu de ses enfants, par défaut. Mais il configure deux écouteurs d'événements, à l'écoute de tous les événements d'erreur et de rejet non gérés dans le navigateur. Ensuite, il examine l'erreur et voit si elle a déjà été traitée par un ErrorBoundaries. Enfin, si ce n'est pas le cas, une boîte de dialogue apparaît, indiquant à l'utilisateur que quelque chose s'est mal passé quelque part, et permet à l'utilisateur de fermer la boîte de dialogue et de continuer à utiliser l'application.

L'erreur a-t-elle déjà été traitée

Avant de harceler les utilisateurs finaux avec des boîtes de dialogue inutiles EN PLUS de la gestion effectuée par ErrorBoundary, nous devons d'abord commencer par demander l'erreur : Avez-vous déjà été traité ? Ma solution à cela consiste à introduire un nouveau champ sur l'objet d'erreur isHandledByBoundary. Ceci est défini sur true dans ErrorBoundary :

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }

Avec cela en place dans tous les composants ErrorBoundary (et autres machines qui gèrent les erreurs non détectées), nous sommes prêts à commencer à définir notre GlobalErrorHandler.

Le squelette nu

Ensuite, nous pouvons construire le squelette de notre GlobalErrorHandler. Il restitue directement ses enfants et restitue également un "ErrorDialog" défini ailleurs. (Si vous souhaitez partager ce composant entre applications, ErrorDialog pourrait être un accessoire à la place.)

import { useState, useEffect, ReactNode } from 'react';
import { ErrorDialog } from '../Components/ErrorDialog';

type Props = {
  children: ReactNode;
};

export function GlobalErrorHandler({ children }: Props) {
  const [error, setError] = useState(null);
  const [isDialogOpen, setDialogOpen] = useState(false);

  useEffect(() => {
    ....
  }, []);

  function handleCloseDialog() {
    setDialogOpen(false);
    setError(null);
  }

  return (
    
      {children}

      {isDialogOpen && error && (
        
      )}
    >
  );
}

La seule chose qui nous manque maintenant, c'est la gestion des erreurs elle-même, définie dans useEffect.

Gérer les erreurs

Tout le code de cette section doit être situé dans la fonction useEffect !

Nous définissons d’abord handleWindowError. Ceci doit être transmis au gestionnaire d'événements d'erreur sur l'objet fenêtre. Rien de mystérieux ici, mais soyez témoin que l'événement d'erreur contient également des informations sur la source, le numéro de ligne et le numéro de colonne. Ce qui pourrait être précieux à collectionner.

Habituellement, ces informations se trouvent également dans l'objet d'erreur, mais je dois mener des enquêtes plus empiriques à ce sujet. Peut-être devrions-nous toujours conserver les numéros de ligne et de colonne tels que rapportés par l'événement d'erreur ? Dans ce cas, nous pourrions également avoir un état pour cela dans GlobalErrorHandler (et nous assurer qu'il est envoyé lors de la journalisation de l'erreur).

   function handleWindowError(
      message: string | Event,
      source?: string,
      lineno?: number,
      colno?: number,
      error?: Error
    ) {
      if (error && (error as any).isHandledByBoundary) {
        return true;
      }

      const errorMessage = error
        ? error
        : `Error: ${message} at ${source}:${lineno}:${colno}`;
      setError(errorMessage);
      setDialogOpen(true);
      return true;
    }

Nous définirons également le gestionnaire handleUnhandledRejection. Ceci concerne les erreurs qui sont générées dans les promesses, mais pour lesquelles nous avons oublié d'écrire une clause .catch().

    function handleUnhandledRejection(event: PromiseRejectionEvent) {
      setError(`Unhandled promise rejection: ${event.reason}`);
      setDialogOpen(true);
    }

Ensuite, tout ce que nous devons faire est de configurer les écouteurs et de les supprimer chaque fois que GlobalErrorHandler n'est plus rendu :

    window.addEventListener('error', handleWindowError);
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('error', handleWindowError);
      window.removeEventListener(
        'unhandledrejection',
        handleUnhandledRejection
      );
    };

Les instructions return sont, bien sûr, l'endroit où nous revenons de la fonction que nous alimentons useEffect. Cela garantit que nous commençons à écouter les événements et à les gérer lorsque le composant est rendu, et que nous nous arrêtons lorsque le composant n'est plus rendu.

Nous avons donc un GlobalEventHandler, pour gérer ces erreurs embêtantes dans notre application React qui sont soit générées à partir de sources asynchrones, soit générées depuis l'extérieur des composants React !

Déclaration de sortie Cet article est reproduit à l'adresse : https://dev.to/lebbe/globalerrorhandler-catch-the-errors-that-falls-through-errorboundarys-fingers-3m5d?1 En cas d'infraction, veuillez contacter [email protected] pour le supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3