How to Use SWR for Data Fetching in React

October, 11th 2024 2 min read

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

bash
npm install swr

Basic Example

jsx
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

jsx
useSWR('/api/user', fetcher, { revalidateOnFocus: true });

Your UI updates instantly whenever the user returns to the tab.


2. Error Retry

jsx
useSWR('/api/user', fetcher, { shouldRetryOnError: true });

Uses exponential backoff internally.


3. Mutations (Update Data Without Re-fetch)

jsx
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)

jsx
useSWR('/api/user', fetcher, { refreshInterval: 5000 });

Great for dashboards and real‑time systems.


Why Choose SWR Over Other Tools?

FeatureSWRReact Query
SizeLightweightLarger
Learning curveVery easyMore concepts
Real‑time focusStrongAlso strong
Best forClient-side React appsComplex 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.