public-rules › TanStack Query techs/tanstack-query

Pass the query's AbortSignal to the request

MEDIUM1.0.0
When to apply Before planning, writing, changing, or reviewing TanStack Query query functions that make network requests or long-running work, especially search-as-you-type, fast navigation, or optimistic updates.

Pass the signal that TanStack Query gives the query function to the underlying request, such as fetch or an HTTP client, so obsolete requests are aborted.

Implementation

  • Destructure signal from the query function's context and pass it to fetch, your HTTP client, or any cancellable work.
  • For custom work, such as a web worker, stop the work when the signal fires.
  • Encode user input in URLs, such as with URLSearchParams, rather than interpolating it raw.
  • Before an optimistic update, await queryClient.cancelQueries for the affected keys.
  • Debounce search-as-you-type input as well; cancellation stops obsolete responses but does not prevent the requests from starting.

Rationale

By default, TanStack Query does not cancel a query when its component unmounts or its key changes; the request finishes and its data is cached. When the query function consumes the signal, TanStack Query aborts the request in those cases, and the query reverts to its previous state. Aborting obsolete requests saves bandwidth and server work, and keeps a slow old response from arriving after a newer one.

Examples

Incorrect (counterexample):

const { data } = useQuery({
  queryKey: ['search', term],
  queryFn: async () => {
    const response = await fetch(`/api/search?q=${term}`);
    return response.json();
  },
});

Typing "abc" leaves the requests for "a" and "ab" running to completion, and the raw term breaks on characters such as &.

Correct:

const { data } = useQuery({
  queryKey: ['search', term],
  queryFn: async ({ signal }) => {
    const response = await fetch(`/api/search?${new URLSearchParams({ q: term })}`, { signal });
    return response.json();
  },
});

When the key changes, the previous request is aborted.

Validation

Type quickly into a search field backed by the query and check in the network panel that superseded requests show as cancelled. Check that query functions making requests pass signal through.

A query function for instant, local work does not need to use the signal.