Apollo refetch does not make a request after network error

Viewed 563

Context

We are currently developing a React Native iOS app with a Graphql back-end. Within this app we would like to show the user a modal when there is no internet connection or when the API is down.

Since we are using Apollo and graphql-code-generator, we have a generated hook in the component that retrieves the data. We show the modal when the hook returns a network error. If a network error has been found, the refetch method from the hook is used to poll and see whether the network or API is back up.

The Problem

This unfortunately does not seem to work, calls to the refetch method after the network has been reestablished do not result in requests. The refetch method also throws a network error.

Code

function useConnectionStatusPolling() {
  // 'useData' is a custom wrapper around the generated hook, that maps and deserialises fields.
  const { loading, refetch, error } = useData();

  // While refreshing, error.networkError is reset.But we would like
  // to keep the error status around until the request works again.
  //
  // For that, we keep the error in the mutable reference, and update it
  // only when the status it not loading. For loading, keep the
  // previous value.
  const networkError = useRef(false);
  if (!loading) {
    networkError.current = !!error?.networkError;
  }

  // Polling is done manually via useInterval because the builtin polling stops
  // if a network error is thrown which we want to ignore in our case.
  useInterval(refetch, networkError.current ? 5000 : "pause");
  return networkError.current;
}
/**
 * Executes a callback at each interval.
 * https://overreacted.io/making-setinterval-declarative-with-react-hooks/
 * @param callback Method to execute after each delay.
 * @param delay Time in miliseconds.
 */
export function useInterval(callback: () => void, delay: number | "pause") {
  const savedCallback = useRef<() => void>();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current?.();
    }
    if (delay !== "pause") {
      const id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

Research & Attempts

We did find out that the error is not cleared as specified in this article. So this hook won't will keep showing the no internet modal and making requests. However this problem still persists after this change, the refetch method just does not make a request to the API. We also tried clearing the cache, but to no avail unfortunately. So I am not really sure what to try at the moment in order to make this work, any advice would be greatly appreciated!

EDIT

Created a small Expo snack (code snippet) that could recreate the issue in a simpler fashion. Here the problem isn't present! Still have no clue why this problems persists in our app though, so all feedback is welcome!

snack

0 Answers
Related