How to implement error handling globally for URQL GraphQL mutation?

How to implement error handling globally for URQL GraphQL mutation?


0

My stack is:

  • react v17.0.2
  • graphql v16.8.0
  • graphql-ws v5.14.0
  • urql v4.0.5

I use Hasura Actions to connect to REST API and I need to implement global error handling for all mutations. For example I have useAuthentication hook that returns a signOut promise:

import { useMutation } from 'urql';

export const useAuthentication = () => {
  const [, signOutMutation] = useMutation(SignOutAction);
  const signOut = async () => {
    const { data } = await signOutMutation({ email: appState.user.email });
    if (data?.signOut.isSuccess) clearAuthState();

    return data?.signOut.isSuccess;
  };

  return { signOut };
}

When the server is down mutation returns error CombinedError: [GraphQL] http exception when calling webhook at makeResult (Connection failure looking in graphQLErrors[0].extensions.internal.error). I can handle it inside signOutMutation and show error notification BUT i have a lot of Hasura Action mutations and I would like to handle such errors globally.

I know about mapExchange and errorExchange but neither onResult nor onError does not return a result because operation is not completed due to Connection failure. I have no idea what exactly returns me CombinedError described above and how to handle it for any query or mutation.

My URQL Client looks like this:

const getWsClient = (headers: StringRecord) => createWSClient({
  url: WS_GRAPHQL_ENDPOINT,
  connectionParams: () => ({ headers })
});

const createUrqlClient = (headers: StringRecord = defaultHeaders) => {
  return createClient({
    url: GRAPHQL_ENDPOINT,
    fetchOptions: {
      headers,
      credentials: 'include'
    },
    exchanges: [
      fetchExchange,
      cacheExchange,
      mapExchange({
        onOperation: (operation) => console.log('operation :>> ', operation),
        onResult: (result) => console.log('result1 :>> ', result),
        onError: (error) => console.log('error :>> ', error)
      }),
      errorExchange({
        onOperation: (operation) => console.log('operation :>> ', operation),
        onResult: (result) => console.log('result2 :>> ', result),
        onError: (error) => console.log('error :>> ', error)
      }),
      subscriptionExchange({
        forwardSubscription(request) {
          const input = { ...request, query: request.query || '' };
          return {
            subscribe(sink) {
              const unsubscribe = getWsClient(headers).subscribe(input, sink);
              return { unsubscribe };
            }
          };
        }
      })
    ]
  });
};

export const useUrqlClient = () => {
  const headers = useHeaders();
  const client = useMemo(() => createUrqlClient(headers), [headers]);
  return client;
};

1 Answer
1


0

Looks like I have found a solution here https://github.com/urql-graphql/urql/discussions/3373



Leave a Reply

Your email address will not be published. Required fields are marked *