DEV Community

Cover image for React Query - Abort Request
Luca Del Puppo for This is Learning

Posted on • Originally published at blog.delpuppo.net on

React Query - Abort Request

Hey Folks,

Today it's time to learn how you can abort an ongoing request with ReactQuery.

Before moving to the example, I want to introduce the AbortSignal.

AbortSignal is a javascript interface used to abort ongoing methods. Typically, you can create an AbortSignal by an AbortController, which simplifies the creation and execution of the AbortSignal. When you create an AbortController (controller = new AbortController()) you get an instance of it that has two core concepts: the signal (controller.signal) and the abort method (controller.abort()).

The first one is important because it contains the signal with its status, and the second one is important because it allows you to change the status of the abort from false to true.

Using these two interfaces, in javascript, you can handle out-of-the-box the abort of an HTTP request created with the fetch API but also with axios if you want. When you create a request, both accept a signal and if you abort that signal you can abort the request.

AbortSignal has also a static method called timeout that accepts a number that describes the timeout time in milliseconds. Using this method you can create easily a signal that changes its status after some time. Very common if you want to handle a timeout of your request.

Just a quick example to make you understand the power of these interfaces.

try {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 5000);
  const res = await fetch(url, { signal: controller.signal });
  const body = await res.json();
} catch (e) {
  if (e.name === "AbortError") {
    // Notify the user of abort.
    // Note this will never be a timeout error!
  } else {
    // A network error, or some other problem.
    console.log(`Type: ${e.name}, Message: ${e.message}`);
  }
} finally {
  clearTimeout(timeoutId);
}
Enter fullscreen mode Exit fullscreen mode

In this example, you can see an abort request created with an AbortController. This example uses a setTimeout method to handle the timeout and as you can notice, when the code creates the fetch API passes the signal status to the fetch. In this way, the fetch request and the signal are linked together. This example could be simplified in this way using the AbortSignal timeout method.

try {
  const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
  const body = await res.json();
} catch (e) {
  if (e.name === "AbortError") {
    // Notify the user of abort.
    // Note this will never be a timeout error!
  } else {
    // A network error, or some other problem.
    console.log(`Type: ${e.name}, Message: ${e.message}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Ok, now you have an idea of how AbortSignal and AbortController work, so we can move on to the next step; how can you abort a request with ReactQuer?

Good news for you, ReactQuery out-of-the-box handles a signal for you for every query and mutation, and your business it's only decided if you want to use it or not.

Let's start with an example

const fetchTodos = async (signal: AbortSignal | undefined): Promise<Todo[]> => {
  const response = await fetch('api/tasks', {
    signal,
  });
  if (!response.ok) {
    throw new ResponseError('Failed to fetch todos', response);
  }
  return await response.json();
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  setUserFilter: Dispatch<SetStateAction<number | null>>;
}

export const useTodos = (): UseTodos => {
  const client = useQueryClient();

  const {
    data: todos = [],
    isLoading,
    isFetching,
    error,
  } = useQuery([QUERY_KEY.todos], ({ signal }) => fetchTodos(signal), {
    refetchOnWindowFocus: false,
    retry: 2
  });

  return {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    setUserFilter,
  };
};
Enter fullscreen mode Exit fullscreen mode

As you can notice, useQuery has a second parameter that contains different options, one of them is the signal. This signal is an AbortSignal that you can use to abort your request if you want. In the example, for instance, the signal is passed to the fetchTodos method and then passed to fetch request.

As you can understand, aborting a request is a piece of cake 🍰

Ok, I think now you have all the notions to abort an HTTP request in javascript and in ReactQuery too.

If you want to go dive into the Abort Request with React query don't miss my Youtube channel 🚀

I think thats all from this article; I hope you enjoyed this content!

See you soon folks

Bye Bye 👋

p.s. you can find the code of the video here

Photo by Rahul Mishra on Unsplash

Top comments (1)

Collapse
 
reacthunter0324 profile image
React Hunter

Great article!
Thank you