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.
npx skills add openai/plugins --skill swr -a codexWhat 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
useSWRInfiniteand a load-more button.
How to install swr
1Skills CLI (Vercel)
npx skills add openai/plugins --skill swr -a codex2Manually: put the files in place
.agents/skills/swr/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add openai/plugins --skill swr -a claude-code2Manually: put the files in place
~/.claude/skills/swr/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/swr/
Manually: put the files in place
.cursor/skills/swr/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install openai/plugins swr2Manually: put the files in place
.github/skills/swr/SKILL.mdPlatform CLI
gemini skills install https://github.com/openai/plugins --path plugins/vercel/skills/swrManually: put the files in place
.devin/skills/swr/SKILL.mdThe legacy .windsurf/skills/ path still works
Claude.ai
Zip the folder and upload it in Settings → Capabilities → 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.