1

I'd like to catch the error in component level and prevent propagation while using the useQuery in @apollo/react-hook. Here is my example code

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

It works fine but at the same time, the error is being propagated to its parents level so I get another error notification message which comes from the error handler at the global level. At the application level, I use the apollo-link-error to manage the Graphql errors.

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

For now, I am finding a solution to stop propagation to top-level so that I can show only InvitationErrorPage and stop displaying error notification at the global level.

Josh Thomas
  • 1,607
  • 2
  • 8
  • 22
  • WHAT??? ... error link just catches errors from ANY graphql responses, it's a part of response processing ... no any kind of propagation here .. just remove error link if you don't want it or react only on network errors – xadm Nov 11 '20 at 15:03
  • yeah, for general graphl error handling, I'd like to do via error link including displaying notification messages. But in a specific case, i.e, invitation page in my case, I need to show "ErrorPage" instead of showing general error notification. – Josh Thomas Nov 11 '20 at 15:20
  • filter by response content [type] ? – xadm Nov 11 '20 at 15:26
  • But I can't actually handle the apollo-server and the Invitation query error has no special content type comparing to generals. So filtering by response content [type] doesn't seem a good solution. – Josh Thomas Nov 11 '20 at 15:31
  • 1
    ehhh .... https://www.apollographql.com/docs/react/api/link/apollo-link-error/#ignoring-errors – xadm Nov 11 '20 at 15:39
  • I got it. Hopefully, it may resolve my issue – Josh Thomas Nov 11 '20 at 19:25

1 Answers1

3

I was also trying to prevent errors from being logged in an Error Link by handling them on a useQuery hook and a further delve into the ApolloLink documentation helped clear up what is happening. The key misunderstanding is that the Error Link is not a parent- or application-level handler, it is request middleware. It's helpful to think about how the data is coming back from the server:

Data flow to client through ApolloLink path.

Thus, when you see an error notification from the Error Link it is not something that "propagated up" from the useQuery hook: it occurred in the request path before the useQuery result was available on the client.

Thus, the onError callback for the Error Link will always be called before any error handling code in the useQuery hook.

Probably your best bet is to use a combination of the operation and graphQLErrors[x].extensions to figure out what errors you should pass through the Error Link middleware like so:

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);
})
dr00
  • 63
  • 5
  • You've made a great impact on my understanding of apollo-error-link. This was exactly the solution that I want before. Thanks for your great answer. – Josh Thomas Dec 15 '20 at 11:44