【问题标题】:How to prevent error propagation in Apollo Client useQuery in react?如何防止 Apollo 客户端 useQuery 中的错误传播?
【发布时间】:2021-02-23 13:20:06
【问题描述】:

我想在 @apollo/react-hook 中使用 useQuery 时捕获组件级别的错误并防止传播。 这是我的示例代码

const invitationDocument = gql`
   query DecodeInvitation($token: String!) {
       DecodeInvitation(token: $token) {
          name
          email
       }
   }
`
const InvitationPage = (props) => {
    const { data, error, loading } = useQuery(invitationDocument, {variables: { token: "XXXX" }});

    if(error)
    {
        return <InvitationErrorPage error={error.message}/>
    }

    return loading? <LoadingPage> : <InvitationAcceptPage />
}

它工作正常,但同时,错误正在传播到它的父级,所以我收到另一个错误通知消息,它​​来自全局级别的错误处理程序。 在应用程序级别,我使用 apollo-link-error 来管理 Graphql 错误。

import { onError } from 'apollo-link-error';
const errorLink = onError (({ graphqlErrors, networkError }) => {
    if(graphqlErrors)
       notification.error(graphqlErrors[0].message);
});
const client = ApolloClient({
   cache: new InMemoryCache(),
   link: ApolloLink.from([
            errorLink,
            new HttpLink({ uri: `http://localhost:8080/graphql`})
          ])
})

目前,我正在寻找一种解决方案来停止传播到顶级,这样我就可以只显示 InvitationErrorPage 并停止在全局级别显示错误通知。

【问题讨论】:

  • 什么??? ...错误链接只是从任何graphql响应中捕获错误,它是响应处理的一部分...这里没有任何传播..如果您不想要它,只需删除错误链接或仅对网络错误做出反应
  • 是的,对于一般的graphl错误处理,我想通过错误链接来做,包括显示通知消息。但在特定情况下,即我的邀请页面,我需要显示“ErrorPage”而不是显示一般错误通知。
  • 按响应内容[类型]过滤?
  • 但是我实际上无法处理 apollo-server 并且邀请查询错误与将军相比没有特殊的内容类型。所以按响应内容[类型]过滤似乎不是一个好的解决方案。

标签: error-handling graphql apollo react-apollo apollo-client


【解决方案1】:

我还试图通过在 useQuery 钩子上处理错误来防止错误被记录到错误链接中,并且进一步深入研究 ApolloLink 文档有助于弄清楚正在发生的事情。关键的误解是错误链接不是父级或应用程序级处理程序,它是请求中间件。考虑数据是如何从服务器返回的会很有帮助:

因此,当您看到来自错误链接的错误通知时,它不是从 useQuery 挂钩“传播”的东西:它发生在请求路径 useQuery 结果之前在客户端上可用。

因此,错误链接的 onError 回调将始终在 useQuery 挂钩中的任何错误处理代码之前调用。

您最好的选择可能是使用operationgraphQLErrors[x].extensions 的组合来确定应该通过错误链接中间件传递哪些错误,如下所示:

const errorLink = onError(({operation, response, graphQLErrors}) => {
  if (!graphQLErrors) {
    return;
  }
  if (operation.operationName === "DecodeInvitation") {
    for (const err of graphQLErrors) {
      if (err.extensions?.code === 'UNAUTHENTICATED') {
        // Return without "notifying"
        return;
      }
    }
  }
  // Notify otherwise
  notification.error(graphqlErrors[0].message);
})

【讨论】:

  • 你对我对 apollo-error-link 的理解产生了很大的影响。这正是我之前想要的解决方案。感谢您的精彩回答。
猜你喜欢
  • 2020-07-25
  • 2020-04-16
  • 2020-09-02
  • 2019-04-11
  • 1970-01-01
  • 2019-10-08
  • 2020-06-04
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多