Rules Hub
Coding Rules Library
Integrate QueryClient in fetch utilities
Pass QueryClient and query keys to fetch utilities to enable caching and deduplication instead of raw fetching.
Bad example
| 1 | export async function fetchUser(id: string, signal?: AbortSignal) { |
| 2 | // Always hits the network, ignoring potential cache |
| 3 | const res = await fetch(`/api/users/${id}`, { signal }); |
| 4 | if (!res.ok) throw new Error('Failed to fetch'); |
| 5 | return res.json(); |
| 6 | } |
| 7 |
|
| 8 | // Usage in a loader |
| 9 | export const loader = async ({ request, params }: LoaderFunctionArgs) => { |
| 10 | return fetchUser(params.id, request.signal); |
| 11 | }; |
Explanation (EN)
The fetch function blindly executes a network request every time it is called. It fails to utilize any caching layer, leading to redundant data fetching and slower user experiences when navigating between known states.
Objašnjenje (HR)
Funkcija za dohvaćanje slijepo izvršava mrežni zahtjev svaki put kad se pozove. Ne koristi nikakav sloj za predmemoriranje (caching), što dovodi do nepotrebnog dohvaćanja podataka i sporijeg korisničkog iskustva pri navigaciji.
Good example
| 1 | import { QueryClient, QueryKey } from '@tanstack/react-query'; |
| 2 |
|
| 3 | interface FetchOptions { |
| 4 | queryClient?: QueryClient; |
| 5 | queryKey?: QueryKey; |
| 6 | signal?: AbortSignal; |
| 7 | } |
| 8 |
|
| 9 | export async function fetchUser(id: string, options: FetchOptions = {}) { |
| 10 | const { queryClient, queryKey, signal } = options; |
| 11 | const fetchFn = async () => { |
| 12 | const res = await fetch(`/api/users/${id}`, { signal }); |
| 13 | if (!res.ok) throw new Error('Failed to fetch'); |
| 14 | return res.json(); |
| 15 | }; |
| 16 |
|
| 17 | // If client and key are present, try cache first or deduplicate request |
| 18 | if (queryClient && queryKey) { |
| 19 | return queryClient.ensureQueryData({ |
| 20 | queryKey, |
| 21 | queryFn: fetchFn, |
| 22 | }); |
| 23 | } |
| 24 |
|
| 25 | return fetchFn(); |
| 26 | } |
| 27 |
|
| 28 | // Usage in a loader |
| 29 | export const loader = async ({ request, params, context }: LoaderFunctionArgs) => { |
| 30 | const queryClient = context.get(queryClientContext); |
| 31 | return fetchUser(params.id, { |
| 32 | queryClient, |
| 33 | queryKey: ['user', params.id], |
| 34 | signal: request.signal, |
| 35 | }); |
| 36 | }; |
Explanation (EN)
The fetch utility now accepts a `QueryClient` and `queryKey`. This allows it to use `ensureQueryData` to return cached data immediately if available, or fetch and cache the result for future use, significantly improving performance.
Objašnjenje (HR)
Funkcija za dohvaćanje sada prihvaća `QueryClient` i `queryKey`. To joj omogućuje korištenje `ensureQueryData` za trenutno vraćanje predmemoriranih podataka ako postoje ili dohvaćanje i spremanje rezultata za buduću upotrebu.