web-dev-qa-db-fra.com

Gestion des erreurs avec react-apollo useMutation hook

J'ai essayé de comprendre ce problème, mais je n'ai pas trouvé de réponse solide. J'essaie d'exécuter une mutation de connexion à l'aide du hook useMutation.

TLDR; je veux savoir quelle est exactement la différence entre le onError passé dans les options et l'erreur qui m'a été donnée par useMutation

Voici mon extrait de code

const [login, { data, loading, error }] = useMutation(LOGIN_QUERY, {
        variables: {
            email,
            password
        },
        onError(err) {
            console.log(err);
        },
});

Côté serveur, j'ai un e-mail prédéfini/codé en dur utilisé pour la connexion et je n'utilise pas Apollo ou tout autre client. Dans le résolveur de cette mutation de connexion, je lance simplement une erreur si l'e-mail n'est pas le même en utilisant

throw new Error('Invalid Email');

Maintenant, je veux gérer cette erreur du côté client (React). Mais ma préoccupation est que si j'utilise "l'erreur" renvoyée par le hook useMutation et que j'essaie de montrer l'erreur de cette manière

render() {
...
{error && <div> Error occured </div>}
...
}

l'erreur est mise à jour dans l'interface utilisateur mais ensuite immédiatement React me montre un écran avec le rejet non géré (erreur): erreur Graphql: mon message d'erreur personnalisé

Mais, si j'utilise onError passé dans les options pour utiliser la fonction Mutate, alors il ne me montre pas cet écran et je peux faire ce que je veux avec l'erreur.

Je veux savoir quelle est exactement la différence entre le onError passé dans les options et l'erreur qui m'a été donnée par useMutation et pourquoi React me montre cet écran d'erreur quand onError est pas utilisé.

Merci!

9
d_bhatnagar

Apollo expose deux types d'erreurs via son API: Erreurs GraphQL , qui sont renvoyées dans la réponse sous la forme errors, à côté de data, et les erreurs de réseau qui se produisent lorsqu'une demande échoue. Une erreur réseau se produit lorsqu'un serveur ne peut pas être atteint ou si le statut de la réponse est autre que 200 - les requêtes qui ont errors dans la réponse peuvent toujours avoir le statut 200. Mais une requête non valide, par exemple, entraînera un état 400 et une erreur de réseau dans Apollo Client.

Apollo Client propose en fait quatre façons différentes de gérer les erreurs de mutation:

1.) L'appel de la fonction mutate retournée par le hook renvoie une promesse. Si la demande aboutit, la promesse sera résoudre vers un objet de réponse qui inclut le data renvoyé par le serveur. Si la demande échoue, la promesse sera rejetée avec l'erreur. C'est pourquoi vous voyez un message "Rejet non géré" dans la console - vous devez gérer la promesse rejetée.

login()
  .then(({ data }) => {
    // you can do something with the response here
  })
  .catch(e => {
    // you can do something with the error here
  })

ou avec la syntaxe async/wait:

try {
  const { data } = await login()
} catch (e) {
  // do something with the error here
}

Par défaut, la Promesse rejettera sur soit les erreurs GraphQL ou les erreurs réseau. En définissant errorPolicy sur ignore ou all, cependant, la Promesse uniquement rejeter sur les erreurs réseau. Dans ce cas, les erreurs GraphQL seront toujours accessibles via l'objet de réponse, mais la promesse se résoudra.

2.) La seule exception à ce qui précède se produit lorsque vous fournissez une fonction onError. Dans ce cas, la promesse sera toujours résolue au lieu de rejeter, mais si une erreur se produit, onError sera appelée avec l'erreur résultante. Le errorPolicy que vous définissez s'applique ici aussi - onError sera toujours appelé pour les erreurs réseau mais ne sera appelé qu'avec des erreurs GraphQL lorsque vous utiliserez le errorPolicy par défaut de none. L'utilisation de onError équivaut à intercepter la promesse rejetée - elle déplace simplement le gestionnaire d'erreurs du site d'appel de la fonction mutate vers le site d'appel du hook.

3.) En plus de la fonction mutate, le hook useMutation renvoie également un objet résultat. Cet objet expose également toutes les erreurs rencontrées lors de l'exécution de la mutation. Contrairement aux fonctions de gestionnaire d'erreurs que nous avons décrites ci-dessus, cet objet error représente l'état de l'application. Les objets error et data exposés de cette manière existent par commodité. Ils sont équivalent pour faire ceci:

const [mutate] = useMutation(YOUR_MUTATION)
const [data, setData] = useState()
const [error, setError] = useState()
const handleClick = async () => {
  try {
    const { data } = await mutate()
    setData(data)
  catch (e) {
    setError(e)
  }
}

Un état d'erreur comme celui-ci peut être utile lorsque vous souhaitez que votre interface utilisateur reflète le fait qu'il y a une erreur. Par exemple, vous pouvez modifier la couleur d'un élément jusqu'à ce que la mutation s'exécute sans erreur. Au lieu d'avoir à écrire vous-même le passe-partout ci-dessus, vous pouvez simplement utiliser l'objet de résultat fourni.

const [mutate, { data, error }] = useMutation(YOUR_MUTATION)

4.) Enfin, vous pouvez également utiliser apollo-link-error pour ajouter global la gestion des erreurs pour vos demandes. Cela vous permet, par exemple, d'afficher une boîte de dialogue d'erreur, quel que soit l'endroit dans votre application à l'origine de la demande.

Laquelle de ces méthodes vous utilisez dans votre application dépend fortement de ce que vous essayez de faire (global vs local, état vs rappel, etc.). La plupart des applications utiliseront plusieurs méthodes de gestion des erreurs.

23
Daniel Rearden