用react-apollo useMutation挂钩处理错误[英] Handling errors with react-apollo useMutation hook

本文是小编为大家收集整理的关于用react-apollo useMutation挂钩处理错误的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我一直在努力解决这个问题,但还没有找到强烈的答案.我正在尝试使用useMutation挂钩执行登录突变.

tldr;我想知道onError在options和error中的差异到底是什么区别

这是我的代码片段

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

在服务器端,我有一个用于登录的预设/硬编码电子邮件,我不使用Apollo或任何其他客户端.在此登录突变的解析器中,如果电子邮件不使用

,我只会丢弃错误
throw new Error('Invalid Email');

现在,我想在客户端(React)上处理此错误.但是我担心的是,如果我使用从useMutation钩中返回的"错误",然后尝试以这种方式显示错误

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

该错误已在UI中更新,但随后立即进行反应显示了一个屏幕:

Unhandled Rejection (Error): Graphql error: My-custom-error-message

但是,如果我使用onError将options传递给useMutate函数,那么它不会向我显示此屏幕,我可以使用错误的任何事情.

我想知道options和error传递给我的onError onError useMutation的onError之间的区别到底是什么,为什么当onError为onError的情况>未使用.

谢谢!

推荐答案

Apollo通过其API暴露了两种错误: graphQl错误,它们作为响应的一部分返回为errors,与data以及网络错误一起返回在请求失败时发生.当无法达到服务器或响应状态为200-响应中的errors查询时,将发生网络错误Apollo客户端将导致400个状态和网络错误.

Apollo客户端实际上提供了处理突变错误的四种不同方法:

1.)调用钩子返回的mutate函数返回承诺.如果请求成功,则承诺将 resolve 对包括服务器返回的data的响应对象.如果请求失败,则承诺将带有错误.这就是为什么您在控制台中看到"未经拒绝"消息的原因 - 您需要处理被拒绝的承诺.

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

或异步/等待语法:

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

默认情况下,承诺将拒绝 graphql错误或网络错误.通过设置 errorpolicyr"> errorpolicy 或all,承诺只会 拒绝网络错误.在这种情况下,GraphQL错误仍将通过响应对象访问,但是承诺将解决.

2.)当您提供onError函数时,上述唯一的例外是.在这种情况下,承诺将始终解析而不是拒绝,但是如果发生错误,则会通过结果错误调用onError.您设置的errorPolicy也适用于此处 - onError将始终为网络错误调用,但在使用none的默认errorPolicy时,只会使用GraphQl错误调用.使用onError等于抓住被拒绝的承诺 - 它只是将错误处理程序从mutate函数的呼叫站点移动到挂钩的呼叫站点.

3.)除mutate函数外,useMutation钩子还返回结果对象.该对象还暴露了运行突变时遇到的任何错误.与我们上面写的错误处理程序函数不同,此error对象表示应用程序状态. error和data在这种方式中暴露的对象都存在方便.他们是等效的:

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)
  }
}

当您希望UI反映出错误时,具有这样的错误状态可能会很有用.例如,您可能会更改元素的颜色,直到突变运行而没有错误.您不必自己写上述样板,而只能使用提供的结果对象.

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

注意:虽然您可以使用裸露的错误状态更新UI,但这样做是不是 实际上 anderling anderling .您必须必须提供onError回调或catch错误以避免警告有关未手持承诺拒绝的警告.

4.)最后,您还可以使用 apollo--- link-error 为您的请求添加全局错误处理.例如,这使您可以显示一个错误对话框,无论您在应用程序中的位置上源是源自的.

您在应用程序中使用的哪种方法在很大程度上取决于您要做的事情(Global vs Local,State vs呼叫等).大多数应用程序将使用多种错误处理方法.

其他推荐答案

const [mutationHandler, { data, loading }] = useMutation(YOUR_MUTATION, {
  onError: (err) => {
      setError(err);
  }
});

这样,我们可以访问带有加载状态和正确处理的数据,以避免控制台/未手持承诺拒绝中的任何错误.

本文地址:https://www.itbaoku.cn/post/1938119.html

问题描述

I have been trying to get my head around this problem but haven't found a strong answer to it. I am trying to execute a login mutation using the useMutation hook.

TLDR; I want to know what exactly is the difference between the onError passed in options and error given to me by the useMutation

Here's my code snippet

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

On the server-side, I have a preset/hardcoded email used for login and I am not using Apollo or any other client. In the resolver of this Login Mutation, I simply throw an error if the email is not same using

throw new Error('Invalid Email');

Now I want to handle this error on the client-side (React). But my concern is that if I use the 'error' returned from the useMutation hook and try to show the error in this way

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

the error is updated in the UI but then immediately React shows me a screen with:

Unhandled Rejection (Error): Graphql error: My-custom-error-message

But, if I use onError passed in options to useMutate function, then it doesn't show me this screen and I can do whatever I want with the error.

I want to know what exactly is the difference between the onError passed in options and error given to me by the useMutation and why does React show me that error screen when onError is not used.

Thanks!

推荐答案

Apollo exposes two kinds of errors through its API: GraphQL errors, which are returned as part of the response as errors, alongside data, and network errors which occur when a request fails. A network error will occur when a server can't be reached or if the response status is anything other than 200 -- queries that have errors in the response can still have a status of 200. But an invalid query, for example, will result in a 400 status and a network error in Apollo Client.

Apollo Client actually provides four different ways to handle mutation errors:

1.) Calling the mutate function returned by the hook returns a Promise. If the request is successful, the Promise will resolve to a response object that includes the data returned by the server. If the request fails, the Promise will reject with the error. This is why you see an "Unhandled Rejection" message in the console -- you need to handle the rejected Promise.

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

or with async/await syntax:

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

By default, the Promise will reject on either GraphQL errors or network errors. By setting the errorPolicy to ignore or all, though, the Promise will only reject on network errors. In this case, the GraphQL errors will still be accessible through the response object, but the Promise will resolve.

2.) The only exception to the above occurs when you provide an onError function. In this case, the Promise will always resolve instead of rejecting, but if an error occurs, onError will be called with the resulting error. The errorPolicy you set applies here too -- onError will always be called for network errors but will only be called with GraphQL errors when using the default errorPolicy of none. Using onError is equivalent to catching the rejected Promise -- it just moves the error handler from the call site of the mutate function to the call site of the hook.

3.) In addition to the mutate function, the useMutation hook also returns a result object. This object also exposes any errors encountered when running the mutation. Unlike the error handler functions we wrote above, this error object represents application state. Both the error and data objects exposed this way exist as a convenience. They are equivalent to doing this:

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)
  }
}

Having error state like this can be useful when you want your UI to reflect the fact there's an error. For example, you might change the color of an element until the mutation runs without an error. Instead of having to write the above boilerplate yourself, you can just use the provided result object.

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

NOTE: While you can use the exposed error state to update your UI, doing so is not a substitute for actually handling the error. You must either provide an onError callback or catch the error in order to avoid warnings about an unhandled Promise rejection.

4.) Lastly, you can also use apollo-link-error to add global error handling for your requests. This allows you to, for example, display an error dialog regardless of where in your application the request originated.

Which of these methods you utilize in your application depends heavily on what you're trying to do (global vs local, state vs callback, etc.). Most applications will make use of more than one method of error handling.

其他推荐答案

const [mutationHandler, { data, loading }] = useMutation(YOUR_MUTATION, {
  onError: (err) => {
      setError(err);
  }
});

With this we can access data with loading status and proper error handling to avoid any error in console / unhandled promise rejection.