Fetching Data with useSWR

A lightweight, declarative way to fetch data in React

What is SWR?

  • SWR stands for stale-while-revalidate
  • A React hook for data fetching, caching, and revalidation
  • Makes remote data feel like local state
  • Built by Vercel

Why Use SWR?

  • Automatic caching
  • Automatic revalidation
  • Focus on UI, not networking boilerplate
  • Optimistic updates
  • Built-in loading and error states
  • Works well with REST, GraphQL, any async fetcher

Installing SWR

npm install swr

Basic Usage

import useSWR from "swr";

const fetcher = url => fetch(url).then(r => r.json());

function Profile() {
  const { data, error, isLoading } = useSWR(
    "/api/user",
    fetcher
  );

  if (error) return <div>Failed to load</div>;
  if (isLoading) return <div>Loading…</div>;

  return <div>Hello {data.name}</div>;
}

What Is Revalidation?

Revalidation is SWR’s core idea for keeping data fresh while keeping UI fast.

SWR always returns:

  1. Stale cached data immediately (fast)
  2. Then revalidates in the background (fresh)
  3. When new data arrives, SWR updates the UI

This gives users:

  • Instant UI (no waiting)
  • Automatically fresh data

When Does Revalidation Happen?

SWR revalidates when:

  • The component mounts
  • The window refocuses
  • The network reconnects
  • The data becomes stale
  • You manually call mutate()
  • You trigger a re-render with a new key

Why Revalidation Matters

Revalidation ensures the UI is:

  • Always up to date
  • Resilient to stale caches
  • Consistent across tabs and sessions

Instead of guessing when to refetch, SWR manages it for you.

Disable Auto Revalidation

Sometimes you may want to disable automatic revalidation:

useSWR("/api/user", fetcher, {
  revalidateOnFocus: false,
  revalidateOnReconnect: false,
  refreshInterval: 0,
});

Manual Revalidation

const { mutate } = useSWR("/api/user", fetcher);

// Force revalidation
mutate();

The SWR Return Object

useSWR(key, fetcher) returns:

const { data, error, isLoading, isValidating, mutate } = useSWR(
  "https://api.github.com/users/octocat",
  fetcher
);

UI Logic Breakdown

if (error) return <p>Failed to load user</p>;
if (isLoading) return <p>Loading…</p>;

return (
  <>
    {isValidating && <p>Updating…</p>}
    <div>
      <h2>{data.name}</h2>
      <p>@{data.login}</p>
      <p>Followers: {data.followers}</p>
      <button onClick={() => mutate()}>Refresh</button>
    </div>
  </>
);

Mutations & Optimistic Updates

const { data, mutate } = useSWR("/api/user", fetcher);

async function updateName(newName) {
  mutate({ ...data, name: newName }, false); // optimistic update
  await fetch("/api/user", { method: "POST", body: JSON.stringify({ name: newName }) });
  mutate(); // revalidate with fresh data
}

Summary

  • SWR simplifies data fetching
  • Revalidation keeps data fresh automatically
  • Stale-while-revalidate improves UX
  • Mutations allow optimistic updates
  • Configuration is flexible and minimal