Réagissez à la gestion et au signalement des erreurs avec les limites d’erreur et la sentinelle – Smashing Magazine


A propos de l’auteur

Développeur frontend génial qui aime tout le codage. Je suis un amoureux de la musique chorale et je travaille pour la rendre plus accessible au monde, un téléchargement à la…
Plus à propos
Chidi

Dans cet article, nous allons explorer le concept de limites d’erreur dans une application React. Nous étudierons un exemple d’application pour voir comment utiliser les limites d’erreur pour offrir une meilleure expérience d’application. Enfin, nous allons intégrer Sentry à notre limite d’erreurs pour le rapport d’erreurs en temps réel.

Dans cet article, nous allons examiner les limites d’erreur dans React. Nous apprendrons ce qu’ils sont et comment les utiliser pour offrir une meilleure expérience utilisateur, même lorsque quelque chose se casse dans notre application. Nous apprendrons également comment intégrer Sentry pour la surveillance des erreurs en temps réel.

Ce didacticiel s’adresse aux développeurs React de tous niveaux qui souhaitent commencer à utiliser les limites d’erreur dans leurs applications React.

La seule condition préalable est que vous maîtrisiez les composants de la classe React.

J’utiliserai Yarn comme gestionnaire de packages pour ce projet. Vous trouverez des instructions d’installation pour votre système d’exploitation spécifique sur ici.

Qu’est-ce qu’une limite d’erreur et pourquoi en avons-nous besoin?

Une image, disent-ils, vaut mille mots. Pour cette raison, je voudrais parler des limites d’erreur en utilisant – vous l’aurez deviné – des images.

L’illustration ci-dessous montre l’arborescence des composants d’une application React simple. Il a un en-tête, une barre latérale à gauche et le composant principal, le tout étant enveloppé par une racine composant.

Un exemple d'arborescence de composants React
Arborescence des composants. (Grand aperçu)

Lors du rendu de ces composants, nous arrivons à quelque chose qui ressemble à l’image ci-dessous.

Vue rendue de l'arborescence des composants précédente
Rendu d’application. (Grand aperçu)

Dans un monde idéal, nous nous attendrions à voir l’application rendue de cette façon à chaque fois. Mais, malheureusement, nous vivons dans un monde non idéal. Des problèmes (bogues) peuvent apparaître dans le frontend, le backend, la fin du développeur et mille autres extrémités. Le problème pourrait se produire dans l’un de nos trois composants ci-dessus. Lorsque cela se produit, notre application magnifiquement conçue s’écroule comme un château de cartes.

React encourage la réflexion en termes de composants. Composer plusieurs composants plus petits est mieux que d’avoir un seul composant géant. Travailler de cette façon nous aide à penser à notre application en unités simples. Mais à part cela, ce ne serait pas bien si nous pouvions contenir des erreurs qui pourraient se produire dans l’un des composants? Pourquoi une défaillance d’un seul composant devrait-elle faire tomber toute la maison?

Au tout début de React, c’était très bien le cas. Et pire, parfois, vous ne pouviez même pas comprendre quel était le problème. Le référentiel React sur Github contient certaines de ces erreurs notables ici, ici, et ici.

React 16 est venu à la rescousse avec le concept de «limite d’erreur». L’idée est simple. Érigez une clôture autour d’un composant pour empêcher tout feu dans ce composant de sortir.

L’illustration ci-dessous montre une arborescence de composants avec un composant enveloppant le

composant. Notez que nous pourrions certainement envelopper les autres composants dans une limite d’erreur si nous le voulions. On pourrait même envelopper le composant dans une limite d’erreur.

Arborescence des composants avec limite d'erreur: un exemple d'arborescence des composants React avec une composante de limite d'erreur.
Arborescence des composants avec limite d’erreur. (Grand aperçu)

Le contour rouge dans l’illustration ci-dessous représente la limite d’erreur lors du rendu de l’application.

Vue rendue de l'arborescence des composants précédente, avec limite d'erreur
Application rendue avec limite d’erreur. (Grand aperçu)

Comme nous l’avons vu précédemment, cette ligne rouge conserve toutes les erreurs qui se produisent dans le

composant de déborder et de s’écraser à la fois le
et Composants. C’est pourquoi nous avons besoin d’une limite d’erreur.

Maintenant que nous avons une compréhension conceptuelle d’une limite d’erreur, passons maintenant aux aspects techniques.

Qu’est-ce qui fait qu’un composant constitue une limite d’erreur?

Comme nous pouvons le voir dans notre arborescence de composants, la limite d’erreur elle-même est un composant React. Selon les documents,

Un composant de classe devient une limite d’erreur s’il définit l’une (ou les deux) des méthodes de cycle de vie static getDerivedStateFromError() ou componentDidCatch().

Il y a deux choses à noter ici. Premièrement, seul un composant de classe peut être utilisé comme limite d’erreur. Même si vous écrivez tous vos composants en tant que fonction, vous devez toujours utiliser un composant de classe si vous souhaitez avoir une limite d’erreur. Deuxièmement, il doit définir soit (soit les deux) static getDerivedStateFromError() ou componentDidCatch(). La ou les définitions que vous définissez dépendent de ce que vous souhaitez accomplir avec votre limite d’erreur.

Fonctions d’une limite d’erreur

Une limite d’erreur n’est pas un mur muet dont le seul but dans la vie est de garder un feu. Les limites d’erreur font un travail réel. Pour commencer, ils attrapent des erreurs javascript. Ils peuvent également consigner ces erreurs et afficher une interface utilisateur de secours. Passons en revue chacune de ces fonctions l’une après l’autre.

Détecter les erreurs JavaScript

Lorsqu’une erreur est lancée à l’intérieur d’un composant, la limite d’erreur est la première ligne de défense. Dans notre dernière illustration, si une erreur se produit lors du rendu du

, la limite d’erreur intercepte cette erreur et l’empêche de se propager vers l’extérieur.

Enregistre ces erreurs

Ceci est entièrement facultatif. Vous pouvez intercepter l’erreur sans l’enregistrer. C’est comme tu veux. Vous pouvez faire ce que vous voulez avec les erreurs levées. Enregistrez-les, enregistrez-les, envoyez-les quelque part, montrez-les à vos utilisateurs (vous ne voulez vraiment pas le faire). C’est à vous.

Mais pour avoir accès aux erreurs, vous devez définir le componentDidCatch() méthode du cycle de vie.

Rendre une interface utilisateur de secours

Ceci, comme la journalisation des erreurs, est entièrement facultatif. Mais imaginez que vous aviez des invités importants et que l’alimentation devait être coupée. Je suis sûr que vous ne voulez pas que vos invités tâtonnent dans le noir, alors vous inventez une technologie pour allumer les bougies instantanément. Magique, hmm. Eh bien, vos utilisateurs sont des invités importants et vous voulez leur offrir la meilleure expérience dans toutes les situations.
Vous pouvez rendre une interface utilisateur de secours avec static getDerivedStateFromError() après qu’une erreur a été levée.

Il est important de noter que les limites d’erreur ne détectent pas les erreurs dans les situations suivantes:

  1. Erreurs dans les gestionnaires d’événements.
  2. Erreurs dans le code asynchrone (par exemple setTimeout ou requestAnimationFrame rappels).
  3. Erreurs qui se produisent lorsque vous effectuez un rendu côté serveur.
  4. Les erreurs sont lancées dans la limite d’erreur elle-même (plutôt que dans ses enfants). Cependant, une autre limite d’erreur pourrait intercepter cette erreur.

Utilisation des limites d’erreur

Plongeons maintenant dans notre éditeur de code. Pour suivre, vous devez cloner le repo.
Après avoir cloné le dépôt, consultez le 01-initial-setup branche. Une fois cela fait, exécutez les commandes suivantes pour démarrer l’application.

# install project dependencies
yarn install

# start the server
yarn start

Une fois lancée, l’application affiche ce que nous avons dans l’image ci-dessous.

L'application de démarrage exécutée dans le navigateur
Vue du navigateur de l’application de démarrage. (Grand aperçu)

L’application a actuellement un en-tête et deux colonnes. Cliquer sur Obtenez des images dans la colonne de gauche fait un appel API à l’URL https://picsum.photos/v2/list?page=0&limit=2 et affiche deux images. Dans la colonne de droite, nous avons quelques textes de description et deux boutons.

Lorsque nous cliquons sur Replace string with object bouton, nous allons remplacer le texte {"function":"I live to crash"}, qui a été stringified, avec l’objet JavaScript simple. Cela déclenchera une erreur car React ne restitue pas les objets JavaScript simples. Cela entraînera le blocage de la page entière et la rendra vierge. Nous devrons actualiser la page pour retrouver notre vue.

Essayez-le par vous-même.

Actualisez maintenant la page et cliquez sur le Invoke event handler bouton. Vous verrez une fenêtre contextuelle d’erreur, avec un peu X dans le coin supérieur droit. Cliquer dessus supprime l’écran d’erreur et vous montre la page rendue, sans avoir besoin de rafraîchir. Dans ce cas, React sait toujours quoi afficher même si une erreur est levée dans le gestionnaire d’événements. Dans un environnement de production, cet écran d’erreur n’apparaîtra pas du tout et la page restera intacte. Vous ne pouvez voir que quelque chose s’est mal passé si vous regardez dans la console du développeur.

Un écran pour nous avertir qu'une erreur s'est produite dans un gestionnaire d'événements.
Alerte d’erreur du gestionnaire d’événements. (Grand aperçu)

Remarque: Pour exécuter l’application en mode production, vous devez installer servir globalement. Après avoir installé le serveur, créez l’application et démarrez-la avec la commande ci-dessous.

# build the app for production
yarn build

# serve the app from the build folder
serve -s build

Après avoir vu comment React gère deux types d’erreurs (erreur de rendu et erreur de gestionnaire d’événements), écrivons maintenant un composant de limite d’erreur.

Créer un nouveau ErrorBoundary.js fichier à l’intérieur du /src dossier et construisons le composant de limite d’erreur morceau par morceau.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class ErrorBoundary extends Component {
  state = {
    error: '',
    errorInfo: '',
    hasError: false,
  };
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  componentDidCatch(error, errorInfo) {
    // eslint-disable-next-line no-console
    console.log({ error, errorInfo });
    this.setState({ errorInfo });
  }
  render() {
    // next code block goes here
  }
}
ErrorBoundary.propTypes = {
  children: PropTypes.oneOfType([ PropTypes.object, PropTypes.array ]).isRequired,
};

Nous définissons les deux méthodes de cycle de vie qui font d’un composant une limite d’erreur. Chaque fois qu’une erreur se produit dans le composant enfant de la limite d’erreur, nos deux méthodes de cycle de vie sont activées.

  1. static getDerivedStateFromError() reçoit l’erreur et met à jour les variables d’état, error et hasError.
  2. componentDidCatch() reçoit le error, qui représente l’erreur qui a été lancée et errorInfo qui est un objet avec un componentStack clé contenant des informations sur le composant qui a provoqué l’erreur. Ici, nous avons enregistré l’erreur et également mis à jour l’état avec le errorInfo. C’est à vous de décider ce que vous voulez faire avec ces deux-là.

Ensuite, dans la méthode de rendu, nous retournons this.props.children, qui représente le composant que cette limite d’erreur contient.

Ajoutons le dernier morceau de code. Copiez le code suivant et collez-le dans le render() méthode.

const { hasError, errorInfo } = this.state;
if (hasError) {
  return (
    

There was an error in loading this page.{' '} { window.location.reload(); }} > Reload this page {' '}

Click for error details {errorInfo && errorInfo.componentStack.toString()}
); }

dans le render() nous vérifions si hasError est vrai. Si c’est le cas, nous rendons le

div, qui est notre interface de secours. Ici, nous montrons des informations sur l’erreur et une option pour recharger la page. Cependant, dans un environnement de production, il n’est pas conseillé de montrer l’erreur à l’utilisateur. Un autre message serait bien.

Utilisons maintenant notre ErrorBoundary composant. S’ouvrir App.js, importer ErrorBoundary et rendre ColumnRight à l’intérieur.

# import the error boundary
import ErrorBoundary from './ErrorBoundary';

# wrap the right column with the error boundary

  

Cliquez maintenant sur Replace string with object. Cette fois, la colonne de droite se bloque et l’interface utilisateur de secours s’affiche. Nous affichons un rapport détaillé indiquant où l’erreur s’est produite. Nous voyons également le journal des erreurs dans la console du développeur.

Vue d'une limite d'erreur montrant une interface utilisateur de secours.
Vue de la limite d’erreur en action. (Grand aperçu)

Nous pouvons voir que tout le reste reste en place. Cliquer sur Get images pour confirmer qu’il fonctionne toujours comme prévu.

À ce stade, je tiens à mentionner qu’avec les limites d’erreur, vous pouvez aller aussi granuleusement que vous le souhaitez. Cela signifie que vous pouvez en utiliser autant que nécessaire. Vous pouvez même avoir plusieurs limites d’erreur dans un seul composant.

Avec notre utilisation actuelle de Error Boundary, en cliquant Replace string with object plante toute la colonne de droite. Voyons comment nous pouvons améliorer cela.

S’ouvrir src/columns/ColumnRight.js, importer ErrorBoundary et rendre le second

bloquer à l’intérieur. Ceci est le paragraphe qui plante le composant.

# import the component
import ErrorBoundary from '../ErrorBoundary';

# render the erring paragraph inside it.

  

Clicking this button will replace the stringified object,{' '} {text}, with the original object. This will result in a rendering error.

Cliquez maintenant sur Replace string with object.

Vue de l'application avec une amélioration de l'utilisation de notre limite d'erreur.
Amélioration de l’utilisation des limites d’erreur. (Grand aperçu)

Cette fois, nous avons encore la majeure partie de la page intacte. Seul le deuxième paragraphe est remplacé par notre interface utilisateur de secours.

Cliquez autour pour vous assurer que tout le reste fonctionne.

Si vous souhaitez consulter mon code à ce stade, vous devriez consulter le 02-create-eb branche.

Au cas où vous vous demanderiez si tout ce problème de limite d’erreur est cool, laissez-moi vous montrer ce que j’ai capturé sur Github il y a quelques jours. Regardez le contour rouge.

Une vue d'un message d'erreur sur Github, avec quelque chose qui ressemble à une limite d'erreur.
Écran d’erreur sur Github. (Grand aperçu)

Je ne suis pas certain de ce qui se passe ici, mais cela ressemble à une limite d’erreur.

Les limites d’erreurs sont cool, mais nous ne voulons pas d’erreurs en premier lieu. Nous devons donc surveiller les erreurs à mesure qu’elles se produisent afin que nous puissions avoir une meilleure idée de la façon de les corriger. Dans cette section, nous apprendrons comment Sentry peut nous aider à cet égard.

Intégration avec Sentry

Lorsque j’ai ouvert le Sentinelle page d’accueil en écrivant cette ligne, j’ai été accueilli par ce message.

Les erreurs logicielles sont inévitables. Le chaos ne l’est pas.
Sentry fournit une surveillance des erreurs auto-hébergée et basée sur le cloud qui aide toutes les équipes logicielles à découvrir, trier et hiérarchiser les erreurs en temps réel.

Sentry est un service de rapport d’erreurs commercial. Il existe de nombreuses autres sociétés qui fournissent des services similaires. Mon choix de Sentry pour cet article est parce qu’il a un plan de développement gratuit qui me permet de me connecter jusqu’à 5000 événements par mois sur tous mes projets (documents de tarification). Un événement est un rapport de plantage (également appelé exception ou erreur). Pour ce tutoriel, nous utiliserons le plan développeur gratuit.

Vous pouvez intégrer Sentry à de nombreux frameworks Web. Passons en revue les étapes pour l’intégrer dans notre projet React.

  1. Visiter le Sentinelle site Web et créez un compte ou connectez-vous si vous en avez déjà un.
  2. Cliquer sur Projects dans la navigation de gauche. Cliquez ensuite sur Create Project pour démarrer un nouveau projet.
  3. En dessous de Choose a platform, sélectionnez Réagir.
  4. En dessous de Set your default alert settings vérifier Alert me on every new issue.
  5. Donnez un nom à votre projet et cliquez sur Create project. Cela créera le projet et vous redirigera vers la page de configuration.

Installons le SDK du navigateur Sentry.

# install Sentry
yarn add @sentry/browser

Sur la page de configuration, copiez le code d’initialisation du SDK du navigateur et collez-le dans votre index.js fichier.

import * as Sentry from '@Sentry/browser';

# Initialize with Data Source Name (dsn)
Sentry.init({ dsn: 'dsn-string' });

Et cela suffit pour que Sentry commence à envoyer des alertes d’erreur. Il est dit dans le docs,

Remarque: Seul, @Sentry/browser signalera toutes les exceptions non capturées déclenchées à partir de votre application.

Cliquer sur Got it! Take me to the issue stream pour passer au tableau de bord des problèmes. Maintenant, revenez à votre application dans le navigateur et cliquez sur les boutons rouges pour lancer une erreur. Vous devriez recevoir des alertes par e-mail pour chaque erreur (parfois les e-mails sont retardés). Actualisez le tableau de bord de vos problèmes pour voir les erreurs.

Tableau de bord des problèmes sentinelle affichant la liste des événements d'erreur.
Tableau de bord des problèmes de sentinelle. (Grand aperçu)

Le tableau de bord Sentry fournit de nombreuses informations sur l’erreur qu’il reçoit. Vous pouvez voir des informations telles qu’un graphique de la fréquence d’occurrence de chaque type d’événement d’erreur. Vous pouvez également affecter chaque erreur à un membre de l’équipe. Il y a une tonne d’informations. Prenez le temps de les explorer pour voir ce qui vous est utile.

Vous pouvez cliquer sur chaque problème pour afficher des informations plus détaillées sur l’événement d’erreur.

Utilisons maintenant Sentry pour signaler les erreurs détectées par notre limite d’erreur. Ouvert ErrorBoundary.js et mettez à jour les morceaux de code suivants.

# import Sentry
import * as Sentry from '@sentry/browser'

# add eventId to state
state = {
  error: '',
  eventId: '', // add this to state
  errorInfo: '',
  hasError: false,
};

# update componentDidCatch
componentDidCatch(error, errorInfo) {
  // eslint-disable-next-line no-console
  console.log({ error, errorInfo });
  Sentry.withScope((scope) => {
    scope.setExtras(errorInfo);
    const eventId = Sentry.captureException(error);
    this.setState({ eventId, errorInfo });
  });
}

Avec cette configuration, Sentry envoie toutes les erreurs capturées par notre limite d’erreur à notre tableau de bord de problème à l’aide du Sentry.captureException méthode.

Sentry nous donne également un outil pour recueillir les commentaires des utilisateurs. Ajoutons le bouton de rétroaction dans le cadre de notre interface de secours à l’intérieur de notre limite d’erreur.

Ouvert ErrorBoundary.js et ajoutez le bouton de rétroaction juste après la div avec un nom de classe de card-body. Vous pouvez placer ce bouton où vous le souhaitez.

...
# add the Sentry button

Maintenant, chaque fois que notre interface de secours est rendue, le Report feedback s’affiche. Cliquer sur ce bouton ouvre une boîte de dialogue que l’utilisateur peut remplir pour nous faire part de ses commentaires.

Dialogue sentinelle avec formulaire de commentaires
Formulaire de commentaires sentinelle. (Grand aperçu)

Allez-y et déclenchez une erreur, puis remplissez et soumettez le formulaire de commentaires. Accédez maintenant à votre tableau de bord Sentry et cliquez sur User Feedback dans la navigation de gauche. Vous devriez voir vos commentaires signalés.

Commentaires Sentry montrant la liste des commentaires des utilisateurs.
Tableau de bord de rétroaction Sentry. (Grand aperçu)

Actuellement, nous recevons des alertes pour chaque erreur, même celles qui se produisent pendant le développement. Cela tend à obstruer notre flux de problèmes. Signalons uniquement les erreurs qui se produisent en production.

Sur la navigation de gauche, cliquez sur Settings. Sous le ORGANIZATION menu, cliquez sur Projects. Dans cette liste, cliquez sur votre projet de limite d’erreur. De Project Settings sur le côté gauche, cliquez sur Inbound Filters. Chercher Filter out events coming from localhost et l’activer. Ce n’est là qu’une des nombreuses configurations disponibles dans Sentry. Je vous encourage à regarder autour de vous pour voir ce qui pourrait être utile pour votre projet.

Si vous souhaitez consulter mon code, la branche correspondante dans mon référentiel est 03-sentinelle-intégrée.

Conclusion

Si vous n’avez pas utilisé de limites d’erreur dans votre application React, vous devez immédiatement en ajouter une au niveau supérieur de votre application. Aussi, je vous encourage à intégrer un service de rapport d’erreurs dans votre projet. Nous avons vu à quel point il est facile de démarrer gratuitement avec Sentry.

La version finale de l’application est hébergé sur Netlify.

Smashing Editorial
(ks, ra, yk, il)
Close Menu