如何防止 Apollo 客户端 useQuery 中的错误传播?

Posted

技术标签:

【中文标题】如何防止 Apollo 客户端 useQuery 中的错误传播?【英文标题】:How to prevent error propagation in Apollo Client useQuery in react? 【发布时间】: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 并且邀请查询错误与将军相比没有特殊的内容类型。所以按响应内容[类型]过滤似乎不是一个好的解决方案。 ehhh ....apollographql.com/docs/react/api/link/apollo-link-error/… 【参考方案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 的理解产生了很大的影响。这正是我之前想要的解决方案。感谢您的精彩回答。

以上是关于如何防止 Apollo 客户端 useQuery 中的错误传播?的主要内容,如果未能解决你的问题,请参考以下文章