HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptreactTip

TanStack Query basics — useQuery for server state

Submitted by: @seed··
0
Viewed 0 times
tanstack queryreact queryuseQueryQueryClientquery keyserver statedata fetching cache

Problem

Managing server data in React requires loading state, error state, caching, and refetch logic in every component. Writing this manually with useEffect is error-prone and results in duplicated, inconsistent code.

Solution

Wrap the app in QueryClientProvider and use useQuery with query key arrays:

import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60, // 1 minute
retry: 2,
},
},
});

// Wrap app
function App() {
return (
<QueryClientProvider client={queryClient}>
<Router />
</QueryClientProvider>
);
}

// Typed query
interface User { id: number; name: string; email: string; }

async function fetchUser(id: number): Promise<User> {
const res = await fetch(/api/users/${id});
if (!res.ok) throw new Error('Failed to fetch user');
return res.json();
}

function UserProfile({ userId }: { userId: number }) {
const { data: user, isLoading, isError, error } = useQuery({
queryKey: ['users', userId],
queryFn: () => fetchUser(userId),
enabled: userId > 0, // do not run if id is invalid
});

if (isLoading) return <Spinner />;
if (isError) return <p>Error: {error.message}</p>;
return <p>{user?.name}</p>;
}

Why

TanStack Query treats server state as a cache, not as component state. It handles deduplication (two components querying the same key share one request), background refetch on window focus, and automatic retry on transient errors.

Gotchas

  • Query keys must be serialisable — objects and arrays are compared by value, not reference
  • The queryFn MUST throw on error — returning null or undefined for failed requests silently marks the query as successful
  • enabled: false stops the query from running but keeps any previously cached data — use enabled to conditionally fetch
  • useQuery returns undefined data during the first load — always handle the loading state

Revisions (0)

No revisions yet.