如何防止 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 中的错误传播?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Apollo 客户端的 useQuery 获取响应头

Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求

Apollo 客户端没有读取使用 useQuery 钩子传入的变量

react native apollo client useQuery invalid hook call error

Apollo 客户端 useQuery 在 useMutation 后不更新数据

@apollo/client 反应钩子 useQuery() 数据未定义