How to prevent that my Apollo Client error handler (onError, error link) is called twice for the same error?

Viewed 402

I'm trying to implement a global error handling for a React application, which uses Apollo Client 3.4.8.

I'm setting up the App and Apollo like this:

const client = new ApolloClient({
  cache: cacheInstance,
  credentials: 'include',
  uri: configuration.API,
  typeDefs,
});

ReactDOM.render(
  <StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </StrictMode>,
  document.getElementById('root')
);

Later on inside the <App /> I add an errorLink:

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    message.error('GraphqlError');
  }
  if (networkError) {
    message.error('NetworkError');
  }
});
client.setLink(from([errorLink, client.link]));

When the server responses with 502 Bad Gateway the error handler gets called twice for the same error.

The first time from http/createHttpLink.ts:

...
            observer.next(err.result);
          }
          observer.error(err);
        });

      return () => {
...

... and the second time from error/index.ts:

...
              return;
            }
            observer.error(networkError);
          },
          complete: () => {
...

Why is this happening that onError is called twice and how to prevent it?

I suspect that I set up the links wrongly?


It' seem like something is wrong with the link chain:

  console.log(client.link);
  client.setLink(from([errorLink, client.link]));
  console.log(client.link);

This results in: Log

1 Answers

So, the issue here is that we can't replace a Link in the chain and when doing this:

client.setLink(from([errorLink, client.link]));

we could be adding multiple error handlers.

The solution is to apply again all the links we need + the new error handler we want to set

// create the HttpLink somewhere and make it available globally
const link = new HttpLink({
  uri: "http://localhost:4000/graphql"
  // Additional options
});

...

// somewhere where we need a different error handler
client.setLink(from([errorLink, httpLink]));
Related