2 ways of handling GraphQL errors in Apollo Client (React)

2 ways of handling GraphQL errors in Apollo Client (React)

If you use Graphql Apollo Client with React there are two ways, more precisely speaking – two levels of handling errors:

  • query/mutation level

  • application level

Query/Mutation level errors handling

In this case, you have access to the dataloading, and error fields, and you can use an error object, which can be used to show a conditional error message.

1const { loading, error, data } = useQuery(YOUR_QUERY);
2
3if (error) return <p>Error :(</p>;

Of course, you can create a component responsible for displaying errors in your app.

1import React from 'react';
2import PropTypes from 'prop-types';
3
4import classes from './ErrorMessage.module.css';
5
6
7const ErrorMessage = (props) => {
8    const { error, ...rest } = props;
9
10    const shouldDisplayError = error && error.message ?
11        <div className={classes.errorMessage} {...rest}>{error.message}</div>
12        :
13        null
14    ;
15
16    return shouldDisplayError;
17};
18
19ErrorMessage.propTypes = {
20    error: PropTypes.shape({
21        message: PropTypes.string.isRequired
22    })
23};
24
25export default ErrorMessage; 

This component is really straightforward. It receives an error as a prop and displays that error to the user.

Application-level error handling

Another approach is handling errors in Application-level. It allows you to create more complex logic.

Application-error handling lets you do whatever you want with errors. For example, you can log those errors to the console in development mode or use external tracking error tools like Sentry on production.

You can use this mechanism to display messages to the user as well. Let’s imagine that you have Messages Context in your app or you have a custom hook, and there you keep the whole logic for adding/removing/displaying messages.

If you use application-level error handling, you can pass error messages to your messages/notification manager and do whatever you want with them.

There are two types of errors.

  1. GraphQL errors (like in a previous example)

  2. Network error (for example, if the app lost internet connection)

To implement application-level error handling, we need to use a functionality called ApolloLink.

The Apollo Link library helps you customize the flow of data between Apollo Client and your GraphQL server. You can define your client's network behavior as a chain of link objects that execute in a sequence.

Each link should represent either a self-contained modification to a GraphQL operation or a side effect (such as logging).

Take a look at a sample implementation of application-level error handling.

First, import the onError function.

1import { onError } from "@apollo/client/link/error";

Second, create the errorLink:

1const errorLink = onError(({ graphQLErrors, networkError }) => {
2    if (graphQLErrors) {
3        console.log(graphQLErrors);
4    }
5
6    if (networkError) {
7        // handle network error
8        console.log(networkError);
9    }
10});

Third, use HttpLink, and from helper method to combine a single link that can be used in the Apollo client.

1import { ApolloClient, InMemoryCache, ApolloProvider, from, HttpLink } from '@apollo/client';
2
3...
4
5const httpLink = new HttpLink({ uri: 'https://<API_URL>' })
6
7const appLink = from([
8    errorLink, httpLink
9])
10
11const client = new ApolloClient({
12    link: appLink,
13    cache: new InMemoryCache(),
14
15});

Summary

There are two types of error that you can handle:

  1. network errors

  2. GraphQL error

Moreover, there are two levels where you can handle those errors:

  1. application level

  2. component (query/mutation) level

Thanks to application-level error handling, you can use JavaScript error tracking tools on production and log errors to the console in local environments. Besides, you can use this mechanism to handle and display errors in your application.

About the author

Marcin Kwiatkowski

Certified Magento Full Stack Developer, based in Poland. He has 7 years of professional Software engineering experience. Privately, husband, father, and DIY enthusiast.

Read more