Gestion des erreurs avec react-apollo useMutation hook

10

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 React me montre immédiatement un écran avec rejet non géré (erreur): erreur Graphql: message d'erreur My-custom-error

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 l'option onError transmise dans les options et l'erreur qui m'a été donnée par useMutation et pourquoi React me montre cet écran d'erreur lorsque onError n'est pas utilisé.

Merci!

d_bhatnagar
la source

Réponses:

33

Apollo expose deux types d'erreurs à travers son API: erreurs GraphQL , qui sont retournés dans le cadre de la réponse que errors, à côté data, et les erreurs de réseau qui se produisent lorsqu'une requête échoue. Une erreur réseau se produit lorsqu'un serveur ne peut pas être atteint ou si l'état de la réponse est autre que 200 - les requêtes qui ont errorsdans la réponse peuvent toujours avoir un état de 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 mutatefonction retournée par le hook renvoie une promesse. Si la demande aboutit, la promesse se résoudra en un objet de réponse qui inclut celui datarenvoyé par le serveur. Si la demande échoue, la Promesse rejettera 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 des erreurs GraphQL ou des erreurs de réseau. En définissant errorPolicy sur ignoreou all, cependant, la promesse ne rejettera que sur les erreurs réseau. Dans ce cas, les erreurs GraphQL seront toujours accessibles via l'objet de réponse, mais la promesse sera résolue.

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

3.) En plus de la mutatefonction, le useMutationhook 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 errorobjet représente l' état de l'application . Les objets erroret ainsi dataexposés existent à titre de commodité. Ils équivalent à 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)

REMARQUE: vous pouvez utiliser l'état d'erreur exposé pour mettre à jour votre interface utilisateur, mais cela ne remplace pas la gestion réelle de l'erreur. Vous devez fournir un onErrorrappel ou catchl'erreur afin d'éviter les avertissements concernant un rejet de promesse non géré.

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

Laquelle de ces méthodes que 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.

Daniel Rearden
la source
Merci pour l'explication ! A voté!
Hyphæne Ohmen
Explication impressionnante et complète. Vous avez gagné un vote positif élevé.
David Fernandez Il y a