SWR and React Query for Data Caching
Use SWR or TanStack Query to fetch, cache, deduplicate, and revalidate server data, replacing manual useEffect fetch patterns.
SWR and React Query for Data Caching is a free Frontend Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Server State Is Different
Network data is not just regular state. It needs: caching, deduplication, background refresh, loading/error tracking, retry. Manual useEffect + useState fetch patterns reimplement these badly.
SWR vs TanStack Query
SWR (Vercel): small, simple, hooks-only. TanStack Query (formerly React Query): bigger, more features (mutations, infinite, prefetching, devtools). Both are excellent.
SWR — Basic Usage
useSWR(key, fetcher) returns data, error, and loading state. Cached by key; deduplicated across components.
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then(r => r.json());
function Profile() {
const { data, error, isLoading } = useSWR('/api/me', fetcher);
if (error) return <ErrorMessage error={error} />;
if (isLoading) return <Spinner />;
return <h1>{data.name}</h1>;
}SWR — Revalidation Behaviour
By default SWR revalidates on focus (tab regains focus) and on reconnect. It returns the cached value immediately ('stale') and updates in the background ('while-revalidate').
SWR — Mutation
mutate(key) revalidates a cached query. Pass new data as the second argument to update optimistically.
import useSWR, { mutate } from 'swr';
async function updateProfile(updates) {
// Optimistic update — UI reflects change immediately
mutate('/api/me', { ...currentData, ...updates }, false);
await fetch('/api/me', { method: 'PUT', body: JSON.stringify(updates) });
// Revalidate to get the server's canonical state
mutate('/api/me');
}TanStack Query — Setup
Wrap your app in a QueryClientProvider with a configured QueryClient.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const client = new QueryClient({
defaultOptions: {
queries: { staleTime: 30000, retry: 2 }
}
});
function App() {
return (
<QueryClientProvider client={client}>
<Routes />
</QueryClientProvider>
);
}useQuery
useQuery({ queryKey, queryFn }) fetches and caches data.
import { useQuery } from '@tanstack/react-query';
function UserList() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(r => r.json()),
staleTime: 60_000 // fresh for 1 minute
});
if (isLoading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
return <ul>{data.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}useMutation for Writes
useMutation handles POST/PUT/DELETE with built-in pending/error state and an onSuccess hook to invalidate caches.
import { useMutation, useQueryClient } from '@tanstack/react-query';
function CreateUserForm() {
const qc = useQueryClient();
const m = useMutation({
mutationFn: (user) => fetch('/api/users', { method: 'POST', body: JSON.stringify(user) }),
onSuccess: () => qc.invalidateQueries({ queryKey: ['users'] })
});
return <button onClick={() => m.mutate({ name: 'Alice' })} disabled={m.isPending}>Create</button>;
}Query Invalidation
After a mutation, invalidate related queries to trigger refetch. queryClient.invalidateQueries({ queryKey: ['users'] }) marks them stale and refetches if mounted.
Optimistic Updates
TanStack Query has first-class optimistic update support via onMutate, onError, and onSettled.
useMutation({
mutationFn: updateUser,
onMutate: async (newUser) => {
await qc.cancelQueries({ queryKey: ['user', newUser.id] });
const previous = qc.getQueryData(['user', newUser.id]);
qc.setQueryData(['user', newUser.id], newUser);
return { previous };
},
onError: (_, newUser, ctx) => {
qc.setQueryData(['user', newUser.id], ctx.previous); // rollback
},
onSettled: (_, __, newUser) => {
qc.invalidateQueries({ queryKey: ['user', newUser.id] });
}
});Infinite Queries
useInfiniteQuery handles paginated/infinite scroll lists — exposes fetchNextPage and tracks all loaded pages.
React Query Devtools
Add @tanstack/react-query-devtools for a floating panel that shows all cached queries, their state, and lets you invalidate manually.
Quick Check
What is the primary benefit of using SWR or TanStack Query over manual useEffect + fetch?
Recap: SWR and React Query
Server state needs caching, dedup, revalidation. SWR: small and simple. TanStack Query: more features (mutations, infinite, devtools). useQuery for reads, useMutation for writes. invalidateQueries after mutations. Optimistic updates with onMutate/onError. Both make manual useEffect+fetch obsolete for production apps.
Frequently asked questions
Is the “SWR and React Query for Data Caching” lesson free?
Yes — the full text of “SWR and React Query for Data Caching” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “SWR and React Query for Data Caching”?
Use SWR or TanStack Query to fetch, cache, deduplicate, and revalidate server data, replacing manual useEffect fetch patterns. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “SWR and React Query for Data Caching” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Fetch API: GET POST PUT DELETE
- Axios: Interceptors and Base URL
- Error Handling: HTTP Status Codes
- SWR and React Query for Data Caching