6
votes

Question

How can I react to Apollo errors in my components?

I'd like for example to display a red banner if a "network offline" error was thrown; or show a modal if an error of a certain type is displayed; or render a <Redirect> (from react-routed-dom) if another kind of error is thrown.

What I tried

I read the documentation chapter about error handling but it only explains how to setup an Apollo link that acts as a middleware to requests in order to catch errors there. As far as I know it's not possible to pass data from that link down to components given that it's a terminating link.

I tried to use error boundary components but it seems like Apollo errors are not really thrown. Not even when using the await syntax.

2
If downvoters would like to explain their downvotes that would be helpful.Shoe
Why would anyone give a downvote (actually 2) to a question?Stefano Magistri
There are trolls everywhere...Piranna

2 Answers

2
votes

As you already pointed out, you could use the apollo-link-error package Link.

If you also use react-router-dom for routing between pages, it is possible to use the browser history or the Redirect component to redirect to an error page with a state object (routing history). The state object contains the error that you would like to show.

The setup could look like this:

  • Create browser history

import { History, createBrowserHistory } from 'history';
   
/* If using Typescript, you can make this object Readonly as follows */
export type ReadonlyBrowserHistory = Readonly<History>
const browserHistory: ReadonlyBrowserHistory = createBrowserHistory();

export default browserHistory;
  • Add Router with browser history (w/ option to make history properties readonly)

import browserHistory from './browserHistory'
import apolloClient from './apolloClient'

... 

ReactDOM.render((
   <ApolloProvider client={apolloClient}>
      <Router history={browserHistory}>
         <App />
      </Router>
   </ApolloProvider>
), document.getElementById("root"));
  • add link with routing to apollo client

import browserHistory from './browserHistory'

const errorLink = onError(({ networkError, graphQLErrors }) => {
   if (graphQLErrors) {
      browserHistory.push("/error", { errors: graphQLErrors });
   }
   else if (networkError) {
      browserHistory.push("/error", { errors: networkError });
   };
});

const httpLink = new HttpLink({
   uri: httpUri
});

const httpLinkWithErrorHandling = ApolloLink.from([
   errorLink,
   httpLink,
]);

const apolloClient = new ApolloClient({
   link,
   ...
});

export default apolloClient;
  • The error page can retrieve the errors from the route location prop

const ErrorPage = ({ location: { state } }) => {

  console.log(state);

  return (<div>error page</div>)
};
0
votes

I fixed my issue by setting the errorPolicy of the query to none then you can catch the graphQLErrors object thrown from the query.

Example:

yourQuery()
    .then()
    .catch((error) => { error.graphQLErrors });