3 votes

React ErrorBoundary - Je n'arrive pas à le faire fonctionner.

Je m'excuse, je sais que la question a déjà été posée, mais je n'arrive pas à trouver un seul exemple qui fonctionne pour moi. Il me semble que ce n'est pas assez facile à comprendre si tant de personnes ont du mal à le comprendre.

J'ai juste besoin de savoir comment attraper les erreurs dans React d'une manière propre et simple. J'utilise CRA 2.0/React 16.7. Je veux un bloc try/catch au niveau de l'action, car c'est là que la logique commerciale est concentrée dans mon application.

J'ai lu cet article et l'ai mis en œuvre comme décrit, mais mon objet ErrorBoundary n'attrape jamais les erreurs.

Ejemplo:

import React, { Component } from "react";

class ErrorBoundary extends Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false };
    }

    static getDerivedStateFromError(error) {
        return { hasError: true };
    }

    componentDidCatch(error, info) {
        console.log("ErrorBoundary: ", error);
        console.log("ErrorBoundary: ", info);
    }

    render() {
        if (this.state.hasError) {
            return <h1>Something went wrong.</h1>;
        }
        return this.props.children;
    }
}

export default ErrorBoundary;

Je suis en train de boucler mes itinéraires au niveau supérieur :

    return (
        <BrowserRouter>
            <ErrorBoundary>
                <div className="main-container">
                    <SideBar />
                    <div className="some-class">
                        <Switch>
                            <Route path="/events" component={Events} />
                            <Route exact path="/" component={Index} />
                        </Switch>
                    </div>
                </div>
            </ErrorBoundary>
        </BrowserRouter>
    );

Dans "events" ci-dessus, je fais un appel à l'API qui génère une erreur 500 du côté de l'API :

componentDidMount() {
    this.props.getAllEvents();
}

Voici l'action de Redux :

export const getAllEvents = () => {
    return async (dispatch, getState) => {
        try {
            let state = getState();
            const result = await get({
                state: state,
                route: "/v1/events"
            });
            dispatch({
                type: GET_EVENTS,
                payload: result
            });
        } catch (e) {
            console.log("Something went wrong at action...");
        }
    };
};

... "get()" ne fait qu'envelopper un GET Axios - rien de bien compliqué.

Je vois une erreur 500 dans la console à cause de l'échec de l'appel API. Je ne vois jamais le message "Something went wrong..." dans la console, à partir du bloc de capture ci-dessus, bien que cette ligne soit atteinte lors du débogage.

La méthode "componentDidCatch()" n'est jamais appelée - "hasError" est toujours faux et les enfants sont toujours rendus.

Si je supprime le bloc de lancement dans le point de terminaison de l'API, tout fonctionne bien et j'obtiens mes données. Je ne suis pas en mesure d'attraper les erreurs au niveau de l'interface utilisateur. J'ai essayé un try/catch dans le "componentDidMount()", j'ai essayé de supprimer le bloc try/catch dans l'action... le comportement ne change pas.

Merci d'avance.

2voto

mehamasum Points 4344

Comme l'autre réponse l'a correctement indiqué, la limite d'erreur de React n'attrape que les erreurs de rendu.

Puisque vous utilisez redux, vous pourriez construire votre propre mécanisme pour des cas comme le vôtre :

  1. Lorsqu'une erreur se produit, vous envoyez une action avec une balise error propriété.
  2. Un réducteur ne recherche que les actions qui ont error propriété. Il reçoit l'action et met à jour un état "erreur globale" dans votre arbre d'état.
  3. Une application connect Le composant wrapper ed voit ce changement d'état et affiche une interface utilisateur de secours.

Par exemple :
Dispatcher une action avec error propriété :

export const getAllEvents = () => {
    return async (dispatch, getState) => {
        try {
            ...
        } catch (e) {
            dispatch({
                type: ERROR, 
                error: e // dispatch an action that has `error` property
            });
        }
    };
};

Un réducteur le voit et met à jour le state.error partie :

export default function errorReducer(state = null, action) {
  const { type, error } = action;
  if (type === RESET_ERROR_MESSAGE) {  // an action to clear the error
    return null;
  } else if (error) { // any type of action, but contains an `error`
    return error;
  }
  return state;
}

Maintenant vous enveloppez votre application dans un connected limite :

function Wrapper({error}) {
  if(error) return <h1>Something went wrong</h1>;
  return <App/>;
}

export default connect(
  state => ({
    error: state.error,
  })
)(Wrapper);

0voto

Andrei Matracaru Points 2534

De la Documentation sur les limites d'erreur de React :

Les limites d'erreur ne capturent pas les erreurs pour :

  • Gestionnaires d'événements (en savoir plus)
  • Code asynchrone (par exemple, les callbacks setTimeout ou requestAnimationFrame)
  • Rendu côté serveur
  • Erreurs lancées dans le cadre d'erreur lui-même (plutôt que dans ses enfants).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X