Agence web » Actualités du digital » Comment utiliser les limites d’erreur de React pour attraper les plantages –

Comment utiliser les limites d’erreur de React pour attraper les plantages –

Les limites d’erreur React vous permettent de détecter les erreurs JavaScript qui se produisent dans les composants enfants. Toute erreur non gérée provenant de la position de l’arborescence de la limite sera détectée, empêchant ainsi un crash.

Vous pouvez afficher votre propre interface utilisateur de secours après qu’une limite d’erreur a intercepté une erreur. Cela vous permet de communiquer gracieusement le problème à l’utilisateur. Ils pourront continuer à utiliser le reste de votre interface sans subir un onglet complètement bloqué.

Création de limites d’erreur

Tout composant de classe React peut devenir une limite d’erreur. Il vous suffit de définir l’une des méthodes de cycle de vie suivantes :

  • componentDidCatch(error) – Cette méthode d’instance sera appelée chaque fois que le composant détecte une erreur. Vous pouvez l’utiliser pour signaler l’erreur à un service d’analyse ou de surveillance.
  • static getDerivedStateFromError(error) – Cette méthode statique peut être utilisée pour mettre à jour l’état de votre composant après une erreur. C’est ainsi que vous affichez une interface utilisateur de secours.

Voici à quoi ressemblent les deux méthodes utilisées :

componentDidCatch()

class MyComponent extends React.Component {
 
    componentDidCatch(error) {
        // use custom reporting framework
        logErrorToAnalytics(error);
        this.props.onError(error);
    }
 
}

Utilisant componentDidCatch(), votre composant peut signaler l’erreur comme bon lui semble. Comme il s’agit d’une méthode d’instance, vous pouvez également la transmettre dans l’arborescence des composants via des props.

getDerivedStateFromError(error)

class MyComponent extends React.Component {
 
    state = {error: null};
 
    render() {
        return <h1>{!this.state.error ? "Hello" : "Error"}</h1>;
    }
 
    static getDerivedStateFromError(error) {
        return {error};
    }
 
}

getDerivedStateFromError() reçoit également l’objet d’erreur JavaScript. Il doit retourner un objet décrivant la transformation d’état à appliquer à votre composant.

React passera l’objet renvoyé à setState(). Dans cet exemple, la valeur du error La clé dans l’état du composant sera définie sur l’objet d’erreur détecté. Cela entraînera la modification de la sortie rendue en Error au lieu de la norme Hello texte.

Quelle méthode utiliser ?

Si les deux méthodes de frontière semblent similaires, c’est qu’elles le sont ! Techniquement, vous pouvez définir l’une ou l’autre de ces méthodes et avoir toujours les mêmes résultats – componentDidCatch() pourrait appeler setState() pour mettre à jour l’état de votre composant, et getDerivedStateFromError() pourrait appeler un service de surveillance externe pour signaler les erreurs qu’il capture.

La différence réside dans le phase dans lequel l’erreur est détectée. componentDidCatch() capture les erreurs dans le phase de validation, après que React a mis à jour le DOM. getDerivedStateFromError() sera appelé lors de la phase de rendu, avant que React ne mette à jour le DOM du navigateur.

Cette subtilité temporelle explique pourquoi getDerivedStateFromError() est généralement utilisé pour basculer vers l’interface utilisateur de secours. Lorsqu’une erreur grave se produit, la mise à jour du DOM peut provoquer d’autres erreurs si votre application est laissée dans un état incohérent. La mise à jour de l’état avant la mise à jour du DOM garantit que l’interface utilisateur de secours s’affiche immédiatement.

Localisation de vos limites d’erreur

Vous êtes libre d’utiliser les limites d’erreur où bon vous semble. Il est recommandé d’utiliser plusieurs limites d’erreur. Ajoutez une limite d’erreur pour chaque couche principale de votre interface utilisateur. Cela vous permet d’isoler les erreurs dans le contenu de votre page du shell de l’application, de sorte qu’un plantage dans un itinéraire ne supprime pas votre barre de navigation.

Voici une hiérarchie de composants simple :

export const () => (
    <App>
        <Header />
        <Router />
        <Footer />
    </App>
);

Dans cette application, le App Le composant est un simple wrapper gérant l’état de niveau supérieur. Header affiche une barre de navigation et Footer affiche la barre inférieure. Le contenu de la page principale – où les plantages sont les plus susceptibles de se produire – est chargé dynamiquement par Router, en fonction de l’URL actuelle.

Par défaut, un plantage dans le Router les enfants assomme tout le site. En plaçant une limite d’erreur autour Router, les erreurs se produisant dans le composant peuvent être gérées avec élégance. L’en-tête et le pied de page restent utilisables tandis que le contenu de la page principale est remplacé par un message de secours.

L’application a besoin d’au moins une limite d’erreur supplémentaire. Envelopper les enfants de App garantit que les erreurs survenant dans l’en-tête ou le pied de page peuvent être détectées. Dans cette situation, il peut être acceptable de remplacer l’intégralité de l’interface utilisateur par un message d’erreur pleine page.

Voici la structure des composants refactorisée :

class ErrorBoundary extends React.Component {
 
    state = {error: null};
 
    render() {
        if (!this.state.error) return this.props.children;
        else return <h1>Error!</h1>;
    }
 
    static getDerivedStateFromError(error) {
        return {error};
    }
 
}
 
export const () => (
    <App>
        <ErrorBoundary>
            <Header>
            <ErrorBoundary>
                <Router />
            </ErrorBoundary>
            <Footer />
        </ErrorBoundary>
    </App>
);

Nous avons résumé la logique de limite d’erreur dans un composant réutilisable. Nous pouvons maintenant envelopper ErrorBoundary autour de tous les composants qui devraient être isolés de leurs parents. N’oubliez pas que vous n’avez pas besoin de créer un composant de limite d’erreur – pour des applications simples ou un composant d’interface utilisateur spécifique, vous pouvez ajouter les hooks de cycle de vie directement dans une classe de composant.

Limites des limites d’erreur

Les limites d’erreur ont des limitations importantes dont vous devez être conscient. Ils sont capables de détecter la plupart des erreurs JavaScript non gérées, mais certaines ne seront pas détectées.

Les limites d’erreur n’intercepteront pas les erreurs qui se produisent dans les méthodes du gestionnaire d’événements. Le code du gestionnaire d’événements n’affecte pas le processus de rendu de React, le framework peut donc toujours rendre vos composants. Comme les erreurs du gestionnaire d’événements n’entraîneront pas de démontage de l’interface utilisateur ou des composants corrompus, React n’essaie pas de les intercepter.

Si vous devez répondre à des erreurs dans vos gestionnaires d’événements, vous devez utiliser un try/catch bloquer. Effectuez une mise à jour de l’état dans le catch instruction pour basculer votre interface utilisateur dans un état d’erreur.

class MyComponent extends React.Component {
 
    state = {error: null};
 
    handleClick = () => {
        try {
            doSomething();
        }
        catch (error) {
            this.setState({error});
        }
    }
 
    render() {
        if (this.state.error) return <p>Error!</p>;
        else return <button onClick={this.handleClick}>Submit</button>
    }
 
}

Mis à part les gestionnaires d’événements, les limites d’erreurs ne peuvent pas détecter les erreurs qui se produisent dans le code asynchrone. Si vous utilisez Promesses, async/await, ou alors setTimeout(), vous devez vous assurer que vous utilisez try/catch/Promise.catch() blocs pour détecter les erreurs qui pourraient se produire.

Un malentendu courant concernant les limites d’erreur concerne l’arbre qu’ils surveillent. Ils peuvent seul intercepter les erreurs qui se produisent plus profondément dans l’arbre. Les limites d’erreur n’attraperont pas les erreurs générées par le composant de limite lui-même.

export default () => (
    <App>                   // Errors won't be caught
        <ErrorBoundary>     // Errors won't be caught
            <Router />      // Errors thrown here will be caught
        </ErrorBoundary>
    </App>
);

Chaque limite d’erreur doit entourer les composants susceptibles de générer une erreur.

Enfin, seuls les composants basés sur les classes peuvent être des limites d’erreur. Il n’existe actuellement aucun mécanisme permettant à un composant fonctionnel de devenir une limite d’erreur. Si vous travaillez dans une base de code fonctionnelle, vous devez créer un composant de limite d’erreur réutilisable comme celui illustré ci-dessus. Vous pouvez ensuite envelopper vos composants avec chaque fois que vous avez besoin d’une limite d’erreur.

Conclusion

Les limites d’erreur apportent du JavaScript try/catch au modèle de rendu déclaratif de React. Ils vous permettent d’isoler des parties de l’interface utilisateur de votre site, de sorte qu’un plantage dans un composant n’affectera pas ses frères et sœurs.

Vous devez évaluer l’interface utilisateur de votre application pour identifier les sections critiques. Placez les limites d’erreur de manière stratégique pour empêcher une erreur non gérée de démonter l’intégralité de votre arborescence de composants. Les utilisateurs sont beaucoup plus susceptibles d’accepter un « quelque chose ne va pas » entièrement stylisé qu’un écran blanc qui doit être rafraîchi.

★★★★★