Skip to content
Development
Skill

/web-data-fetching-swr

SWR data fetching patterns — keys and fetchers, isLoading vs isValidating, revalidation strategy, useSWRMutation, useSWRInfinite, conditional fetching

From plugin
skills
26200 skills

Claude Code

$ npx -y skills add agents-inc/skills --skill web-data-fetching-swr --agent claude-code

SKILL.md

web-data-fetching-swr.SKILL.md
name: web-data-fetching-swr
description: SWR data fetching patterns — keys and fetchers, isLoading vs isValidating, revalidation strategy, useSWRMutation, useSWRInfinite, conditional fetching

SWR Patterns

> **Quick Guide:** SWR renders the cached value immediately and revalidates behind it, so the cache > key is the whole identity of a request and an unstable key is the single most expensive mistake > here. `isLoading` covers the first fetch only and `isValidating` covers every fetch, which is why > using the second as a spinner hides the data SWR exists to show. Reads are `useSWR`, writes are > `useSWRMutation`, and a `null` key is how a request is skipped without breaking the rules of hooks.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — fetchers, key shapes, state handling, `SWRConfig`
  • [examples/mutations.md](examples/mutations.md) — `useSWRMutation`, optimistic updates, `populateCache`, global `mutate`
  • [examples/caching.md](examples/caching.md) — revalidation strategies, prefetching, cache persistence
  • [examples/pagination.md](examples/pagination.md) — `useSWRInfinite`, infinite scroll, offset and filtered paging
  • [examples/conditional.md](examples/conditional.md) — the null key, dependent queries, function keys
  • [examples/error-handling.md](examples/error-handling.md) — retry policy, status-specific handling, offline
  • [examples/suspense.md](examples/suspense.md) — suspense mode and server-rendered fallback data
  • [reference.md](reference.md) — every config option with its default, and the hook return shapes

---

Which path applies

  • **Reading a resource** — `useSWR`, which fetches on mount and keeps the value fresh. Patterns 1–3.
  • **Writing** — `useSWRMutation`, which does nothing until `trigger()` is called. Pattern 4.
  • **A list that grows** — `useSWRInfinite`, whose `getKey(pageIndex, previousPage)` both builds each

page's key and signals the end by returning `null`. Pattern 7.

  • **Suspense instead of loading branches** — `suspense: true` makes the component suspend and `data`

non-null; see [examples/suspense.md](examples/suspense.md). Everything else here still applies.

---

<critical_requirements>

Before writing SWR code

**Give each request a key that is stable across renders — a string, or an array of primitives.** The key is the cache identity and the dependency: an object or array literal is a new reference every render, so SWR sees a new key, fetches again, re-renders, and repeats.

**Throw from the fetcher on a non-OK response.** SWR's error state is driven by a rejected promise, so a fetcher that returns `res.json()` unconditionally hands the error body over as `data` and no error branch ever runs.

**Branch on `isLoading` for the first fetch and `isValidating` for a refresh in progress.** `isLoading` is true only when there is no data yet, which is exactly when a skeleton is right; `isValidating` is true during background revalidation, when there is data on screen to keep.

**Reach for `useSWRMutation` for anything that writes.** `useSWR` fires on mount, so a POST written as a `useSWR` fetcher sends itself as soon as the component renders.

</critical_requirements>

---

**Auto-detection:** `useSWR`, `useSWRMutation`, `useSWRInfinite`, `useSWRImmutable`, `SWRConfig`, `useSWRConfig`, `mutate`, `trigger`, `isValidating`, `revalidateOnFocus`, `dedupingInterval`, `keepPreviousData`, `fallbackData`, `optimisticData`, `rollbackOnError`, `populateCache`, `preload`, `swr/mutation`, `swr/infinite`, `swr/immutable`

**Applies to:**

  • Cache keys, fetchers and the shape of what a hook returns
  • Revalidation policy: focus, reconnect, interval, stale, and disabling all of it
  • Writes, optimistic updates and cache invalidation after them
  • Cursor and offset pagination that accumulates pages
  • Conditional and dependent fetching
  • Retry policy and hydrating from server-rendered data

**Handled elsewhere:**

  • Client state that never came from a server — this skill caches responses
  • The transport itself; a fetcher is any function returning a promise, and what it uses is open
  • How an error boundary is built — this skill settles which option throws an error into one
  • APIs addressed through a graph query language, whose clients cache normalised entities rather than

whole responses under a key

---

<philosophy>

Philosophy

The name is the algorithm: return what is cached, revalidate behind it, re-render if the answer changed. A component therefore has data at nearly every moment of its life, and the interesting states are not "loading or loaded" but "is this being checked" and "is this out of date".

Everything else follows. The key is a global identity, so two components asking for the same key share one request and one cache entry with no coordination between them. Revalidation is triggered by events the user causes — refocusing the tab, reconnecting — rather than by timers, because those are the moments the data on screen is most likely to be stale.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: The fetcher

interface FetchError extends Error {
  info: unknown;
  status: number;
}

const fetcher = async <T>(url: string): Promise<T> => {
  const response = await fetch(url);
  if (!response.ok) {
    const error = new Error("Fetch failed") as FetchError;
    error.info = await response.json().catch(() => null);
    error.status = response.status;
    throw error;
  }
  return response.json();
};

Attaching `status` is what lets a component tell a 404 from a 500, and lets a retry policy decline to retry either. Define the fetcher at module scope — one created inside a component is a new reference on every render.

Full code: [examples/core.md](examples/core.md) — client-based and multi-argument fetchers

---

Pattern 2: isLoading vs isValidating

// data: undefined, isLoading: true,  isValidating: true   — first fetch
// data: T,         isLoading: false, isValidating: fal
Read more
@agents-inc
Ships withskills

The official skills marketplace for Agents Inc. 230+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Stars on GitHub

Momentum

stars in total
26
Star history of agents-inc/skills on GitHub, a chart by star-history.com

Other skills on skills.

ai-infrastructure-litellm

ai-infrastructure-lite…

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…

@agents-inc@agents-incInstall Skill
ai-infrastructure-modal

ai-infrastructure-moda…

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…

@agents-inc@agents-incInstall Skill
ai-infrastructure-ollama

ai-infrastructure-olla…

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…

@agents-inc@agents-incInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about web-data-fetching-swr.

Which coding agents can use web-data-fetching-swr?
web-data-fetching-swr installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.