Skip to main content
skill CX Codex GP ChatGPT official · OpenAI

swr · openai — Codex skill: what it does, how to install

Guidance for using SWR in React apps with client-side fetching, caching, revalidation, mutations, pagination, and live data.

Install into Codex · Skills CLI (Vercel) All methods and platforms ↓
npx skills add openai/plugins --skill swr -a codex
Open on GitHub

What swr does

This skill guides React work built around the SWR library. It covers useSWR, resource keys, fetcher functions, loading and error states, shared cache behavior, and manual refreshes through mutate(). The material also explains how SWRConfig can provide shared defaults for an application or subtree.

Separate sections cover useSWRMutation for server changes and optimistic UI, including rollback after a failed request. useSWRInfinite handles paginated and load-more interfaces, while subscription guidance covers WebSockets and SSE with cleanup and shared subscriptions. Error retry rules and conditional fetching are included too.

Hooks must not be called conditionally. Pass null as the key when a request should be skipped. The project needs React and the swr package; the skill itself can be added to Codex with the commands listed below.

What it helps with

  • set up client-side React fetching with SWR
  • share cached results across components
  • add optimistic server mutations with rollback
  • build pagination or a load-more list
  • configure retries and real-time subscriptions

Example prompts for the agent

  • Set up a profile request with useSWR, including loading and error states.
  • Implement a user update with useSWRMutation, optimistic data, and rollback on failure.
  • Build a paginated items list with useSWRInfinite and a load-more button.

How to install swr

1Skills CLI (Vercel)

npx skills add openai/plugins --skill swr -a codex

2Manually: put the files in place

.agents/skills/swr/SKILL.md

For all projects use ~/.agents/skills/

Step by step, with commands for each platform: Codex skills: how to install, where they live, how to call them

Questions about swr

How do I install swr in Codex?

Run npx skills add openai/plugins --skill swr, then run npx skills add openai/plugins --skill swr -a codex. The skill file is placed at .agents/skills/swr/SKILL.md.

What does the swr skill do?

It provides guidance for SWR-based data fetching in React, including caching, revalidation, mutations, optimistic updates, pagination, retries, and subscriptions.

How can I skip an SWR request when an ID is missing?

Use null as the key, such as useSWR(userId ? "/api/user/${userId}" : null, fetcher). Do not call the hook conditionally.

Source text

SKILL.md · Apache-2.0
---
name: swr
description: SWR data-fetching expert guidance. Use when building React apps with client-side data fetching, caching, revalidation, mutations, optimistic UI, pagination, or infinite loading using the SWR library.
metadata:
  priority: 4
  docs:
    - "https://swr.vercel.app/docs"
  sitemap: "https://swr.vercel.app/sitemap.xml"
  pathPatterns:
    - 'lib/fetcher.*'
    - 'src/lib/fetcher.*'
    - 'utils/fetcher.*'
    - 'src/utils/fetcher.*'
    - 'hooks/use*SWR*'
    - 'src/hooks/use*SWR*'
    - 'hooks/useFetch*'
    - 'src/hooks/useFetch*'
  importPatterns:
    - 'swr'
    - 'swr/*'
  bashPatterns:
    - '\bnpm\s+(install|i|add)\s+[^\n]*\bswr\b'
    - '\bpnpm\s+(install|i|add)\s+[^\n]*\bswr\b'
    - '\bbun\s+(install|i|add)\s+[^\n]*\bswr\b'
    - '\byarn\s+add\s+[^\n]*\bswr\b'
  promptSignals:
    phrases:
      - "swr"
      - "useswr"
      - "stale-while-revalidate"
    allOf:
      - [data fetching, client]
      - [cache, revalidat]
    anyOf:
      - "mutation"
      - "optimistic"
      - "infinite loading"
      - "pagination"
    noneOf: []
    minScore: 6
---

# SWR — React Hooks for Data Fetching

You are an expert in SWR v2 (latest: 2.4.1), the React Hooks library for data fetching by Vercel. SWR implements the stale-while-revalidate HTTP cache invalidation strategy — serve from cache first, then revalidate in the background.

## Installation

```bash
npm install swr
```

## Core API

### `useSWR`

```tsx
import useSWR from 'swr'

const fetcher = (url: string) => fetch(url).then(res => res.json())

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

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error loading data</div>
  return <div>Hello, {data.name}</div>
}
```

**Key parameters:**
- `key` — unique string, array, or function identifying the resource (often a URL)
- `fetcher` — async function that receives the key and returns data
- `options` — optional config object

**Return values:** `data`, `error`, `isLoading`, `isValidating`, `mutate`

### `useSWRMutation` — Remote Mutations

```tsx
import useSWRMutation from 'swr/mutation'

async function updateUser(url: string, { arg }: { arg: { name: string } }) {
  return fetch(url, { method: 'POST', body: JSON.stringify(arg) }).then(res => res.json())
}

function Profile() {
  const { trigger, isMutating } = useSWRMutation('/api/user', updateUser)

  return (
    <button disabled={isMutating} onClick={() => trigger({ name: 'New Name' })}>
      Update
    </button>
  )
}
```

### `useSWRInfinite` — Pagination & Infinite Loading

```tsx
import useSWRInfinite from 'swr/infinite'

const getKey = (pageIndex: number, previousPageData: any[]) => {
  if (previousPageData && !previousPageData.length) return null
  return `/api/items?page=${pageIndex}`
}

function Items() {
  const { data, size, setSize, isLoading } = useSWRInfinite(getKey, fetcher)
  const items = data ? data.flat() : []

  return (
    <>
      {items.map(item => <div key={item.id}>{item.name}</div>)}
      <button onClick={() => setSize(size + 1)}>Load More</button>
    </>
  )
}
```

## Global Configuration

Wrap your app (or a subtree) with `SWRConfig` to set defaults:

```tsx
import { SWRConfig } from 'swr'

function App() {
  return (
    <SWRConfig value={{
      fetcher: (url: string) => fetch(url).then(res => res.json()),
      revalidateOnFocus: false,
      dedupingInterval: 5000,
    }}>
      <Dashboard />
    </SWRConfig>
  )
}
```

## Revalidation Strategies

| Strategy | Option | Default |
|---|---|---|
| On window focus | `revalidateOnFocus` | `true` |
| On network recovery | `revalidateOnReconnect` | `true` |
| On mount if stale | `revalidateIfStale` | `true` |
| Polling | `refreshInterval` | `0` (disabled) |
| Manual | Call `mutate()` | — |

## Optimistic Updates

```tsx
const { trigger } = useSWRMutation('/api/user', updateUser, {
  optimisticData: (current) => ({ ...current, name: 'New Name' }),
  rollbackOnError: true,
  populateCache: true,
  revalidate: false,
})
```

## Conditional Fetching

Pass `null` or a falsy key to skip fetching:

```tsx
const { data } = useSWR(userId ? `/api/user/${userId}` : null, fetcher)
```

## Error Retry

SWR retries on error by default with exponential backoff. Customize with:

```tsx
useSWR(key, fetcher, {
  onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
    if (error.status === 404) return // Don't retry on 404
    if (retryCount >= 3) return      // Max 3 retries
    setTimeout(() => revalidate({ retryCount }), 5000)
  },
})
```

## `useSWRSubscription` — Real-Time Data Sources

Subscribe to real-time data (WebSockets, SSE, etc.) with automatic deduplication:

```tsx
import useSWRSubscription from 'swr/subscription'

function LivePrice({ symbol }: { symbol: string }) {
  const { data } = useSWRSubscription(
    `wss://stream.example.com/${symbol}`,
    (key, { next }) => {
      const ws = new WebSocket(key)
      ws.onmessage = (event) => next(null, JSON.parse(event.data))
      ws.onerror = (event) => next(event)
      return () => ws.close()
    }
  )

  return <span>{data?.price}</span>
}
```

The `subscribe` function receives a `next(error, data)` callback and must return a cleanup function. Multiple components using the same key share a single subscription.

## Key Rules

- **Keys must be unique** — two `useSWR` calls with the same key share cache and deduplicate requests
- **Fetcher is optional** when set via `SWRConfig`
- **`mutate(key)`** globally revalidates any hook matching that key
- **Array keys** like `useSWR(['/api/user', id], fetcher)` — the fetcher receives the full array
- **Never call hooks conditionally** — use conditional keys (`null`) instead

© Vercel Labs · Apache-2.0 · openai/plugins

Similar skills

All skills for Frontend and UI →

swr by other authors comes first.

From the same set528

The whole set →
cloudflare A skill that helps your agent pick the right Cloudflare product and check the docs instead of relying on stale training data. CX Codex GP ChatGPT 7installs grammar-of-graphics-and-declarative-visualization Generates tabular charts using Vega-Lite, Vega, and Observable Plot. It guides the model to pick the right declarative grammar instead of writing bespoke rendering code. CX Codex GP ChatGPT 7installs vercel-storage Tells the agent which Vercel storage to pick and how to wire it up: Blob, Edge Config, Neon Postgres, Upstash Redis. CX Codex GP ChatGPT 6installs vercel-queues Guides your coding agent on Vercel Queues: message publishing, push and poll consumer routes, and vercel.json triggers. Useful for async pipelines on Node.js 22+. CX Codex GP ChatGPT 6installs satori Guides dynamic Open Graph image generation in Next.js using Satori and @vercel/og with HTML and CSS. CX Codex GP ChatGPT 6installs runtime-cache This skill explains Vercel Runtime Cache for regional key-value caching and tag-based invalidation. Use it when framework-level caching is not enough. CX Codex GP ChatGPT 6installs routing-middleware Guides your agent on Vercel Routing Middleware to intercept requests before cache, handle rewrites, redirects, and configure Edge, Node.js, or Bun. CX Codex GP ChatGPT 6installs investigation-mode Coordinates debugging for stuck or broken processes by checking logs, workflow status, the browser, and deployment state. Useful when a failure has no clear cause. CX Codex GP ChatGPT 6installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor