How to Use SWR for Data Fetching in React
Modern React apps rely heavily on smooth, efficient data fetching. But managing loading states, caching, revalidation, retry logic, and UI updates manually quickly becomes messy.
SWR (Stale‑While‑Revalidate), created by Vercel, solves these problems with a tiny API and powerful built‑in behaviors.
By the end of this guide, you’ll understand how SWR handles caching, background updates, mutations, revalidation, polling, and error handling—all while keeping your components clean and predictable.
What Is SWR?
SWR is built around a simple but powerful idea:
Serve cached data immediately → fetch fresh data in the background → update UI automatically
This creates a UI that feels fast, responsive, and always up‑to‑date.
Key benefits:
- ⚡ Instant rendering from cache
- 🔄 Automatic revalidation
- 🔁 Retry logic with exponential backoff
- 🔍 Real-time updates (focus, reconnect, polling)
- 🔧 Easy mutations (POST, PUT, DELETE)
- 🧵 Minimal boilerplate
Installing SWR
npm install swrBasic Example
import useSWR from 'swr';
const fetcher = url => fetch(url).then(r => r.json());
function Profile() {
const { data, error } = useSWR('/api/user', fetcher);
if (error) return <div>Failed to load user</div>;
if (!data) return <div>Loading…</div>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
}
export default Profile;Why this works so well:
- SWR shows cached data immediately
- Then fetches fresh data
- Then updates the UI automatically
- And does this again when you focus the tab or reconnect
Useful SWR Features
1. Revalidate On Focus
useSWR('/api/user', fetcher, { revalidateOnFocus: true });Your UI updates instantly whenever the user returns to the tab.
2. Error Retry
useSWR('/api/user', fetcher, { shouldRetryOnError: true });Uses exponential backoff internally.
3. Mutations (Update Data Without Re-fetch)
import useSWR, { mutate } from 'swr';
const fetcher = url => fetch(url).then(r => r.json());
function Profile() {
const { data } = useSWR('/api/user', fetcher);
const updateUser = async () => {
await fetch('/api/user', {
method: 'PUT',
body: JSON.stringify({ name: 'New Name' }),
});
mutate('/api/user'); // refresh cache
};
return (
<div>
<h1>{data?.name}</h1>
<button onClick={updateUser}>Update Name</button>
</div>
);
}This updates the cached data instantly, even before the server responds.
4. Polling (Refresh Interval)
useSWR('/api/user', fetcher, { refreshInterval: 5000 });Great for dashboards and real‑time systems.
Why Choose SWR Over Other Tools?
| Feature | SWR | React Query |
|---|---|---|
| Size | Lightweight | Larger |
| Learning curve | Very easy | More concepts |
| Real‑time focus | Strong | Also strong |
| Best for | Client-side React apps | Complex multi-cache apps |
If you need a simple, powerful, lightweight data fetching solution—SWR is ideal.
Conclusion
SWR gives you:
- Instant cached data
- Background revalidation
- Automatic UI updates
- Minimal code
- A smooth, real‑time feel
Once you start using SWR, it’s hard to go back to manual useEffect + fetch boilerplate.
To explore more advanced features (pagination, optimistic updates, key generators), check the official docs:
👉 https://swr.vercel.app/docs/getting-started
If you want, I can generate:
- a Next.js SWR example,
- a custom SWR fetcher with Axios,
- or a full SWR + TypeScript cheat sheet.