Rules Hub

Coding Rules Library

← Back to all rules
frontend ruleStack: react
react-routerreact-queryperformanceasyncabort-signal

Merge AbortSignals when bridging async contexts

Combine cancellation signals when using async libraries (like React Query) within framework lifecycles (like React Router) to ensure redundant requests are properly aborted.

PR: Feat/FCK-2245 - Cache Bellsheep and profile loaders with TanStack Query #343Created: Dec 10, 2025

Bad example

Old codets
1export const loader = ({ request }: LoaderFunctionArgs) => {
2 return queryClient.fetchQuery({
3 queryKey: ['user', params.id],
4 // Only uses React Query's signal, ignoring React Router's navigation cancellation
5 queryFn: ({ signal }) => fetch(`/api/user/${params.id}`, { signal }),
6 });
7};

Explanation (EN)

This code only respects the signal from the query library (React Query). If the user navigates away (triggering React Router's `request.signal`), the network request continues running unnecessarily because that signal is ignored.

Objašnjenje (HR)

Ovaj kod poštuje samo signal iz biblioteke za upite (React Query). Ako korisnik promijeni stranicu (što aktivira `request.signal` React Routera), mrežni zahtjev nastavlja raditi nepotrebno jer se taj signal ignorira.

Good example

New codets
1import { mergeAbortSignals } from '@/lib/utils';
2
3export const loader = ({ request }: LoaderFunctionArgs) => {
4 return queryClient.fetchQuery({
5 queryKey: ['user', params.id],
6 queryFn: ({ signal: querySignal }) => {
7 // Combines navigation cancellation (request.signal) with query cancellation (querySignal)
8 const finalSignal = mergeAbortSignals(request.signal, querySignal);
9 return fetch(`/api/user/${params.id}`, { signal: finalSignal });
10 },
11 });
12};

Explanation (EN)

The signals are merged. The request now aborts if *either* the user navigates away (React Router) OR the query is cancelled internally (React Query, e.g., via timeout or unmount).

Objašnjenje (HR)

Signali su spojeni. Zahtjev se sada prekida ako korisnik promijeni stranicu (React Router) *ili* ako se upit interno otkaže (React Query, npr. zbog isteka vremena ili demontaže komponente).

Notes (EN)

Modern environments support `AbortSignal.any()`, but a polyfill or custom helper is needed for broader compatibility.

Bilješke (HR)

Moderna okruženja podržavaju `AbortSignal.any()`, ali za širu kompatibilnost potreban je polyfill ili vlastita pomoćna funkcija.