useSWR入門
データ取得をもっと楽に、もっと速く。そんな願いを叶えるのが Vercel 製のデータフェッチングライブラリ「SWR」です。ReactのuseEffect + fetchよりもシンプルに、キャッシュや再検証(Revalidation)まで面倒を見てくれます(便利です)。
この記事で学べること
- SWRの基本概念(Stale-While-Revalidate)
- 最小コードでのデータ取得
- ローディング・エラー表示のパターン
- グローバル設定(SWRConfig)
- 再検証のタイミング制御(focus/reconnect/interval)
- ミューテーション(書き込みとキャッシュ更新)
- 依存キー・条件付きフェッチ
基本概念:Stale-While-Revalidate とは
SWRは「手元のキャッシュ(stale)をすぐ表示しつつ、裏で最新データを取りに行き(revalidate)、更新できたらUIを差し替える」という戦略です。ユーザーは待たされず、でもデータは新鮮。いいとこ取りというわけです。
まずは使ってみる
インストール(プロジェクトで一度だけ)
npm i swr
基本の使い方:
import useSWR from "swr";
const fetcher = (url: string) => fetch(url).then((r) => r.json());
export default function Profile() {
const { data, error, isLoading } = useSWR(
"https://jsonplaceholder.typicode.com/users/1",
fetcher,
);
if (isLoading) return <p>読み込み中...</p>;
if (error) return <p>エラーが発生しました</p>;
return (
<div>
<h2>{data.name}</h2>
<small>ID: {data.id}</small>
</div>
);
}
Note:
fetcherは「URLを受け取ってデータを返す関数」。SWRはこのfetcherにURL(キー)を渡して実行します。
ローディング・エラー・データ
SWRは状態管理も内蔵しています。
isLoading: まだ最初のデータがない状態error: フェッチに失敗したときのエラーdata: フェッチ済みデータ(キャッシュを含む)
すでにキャッシュがあれば
isLoadingでもdataがある、という状態も起こり得ます(SWRの肝です)。
SWRConfig でグローバル設定
import { SWRConfig } from "swr";
const fetcher = (url: string) => fetch(url).then((r) => r.json());
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<SWRConfig
value={{
fetcher,
shouldRetryOnError: true,
errorRetryCount: 3,
revalidateOnFocus: true,
revalidateOnReconnect: true,
}}
>
{children}
</SWRConfig>
);
}
Note: ここで指定した
fetcherがデフォルトになります。各コンポーネントで省略可能に(楽ですね)。
再検証タイミングをコントロール
revalidateOnFocus: タブに戻ったら再取得(ユーザーに最新を見せる)revalidateOnReconnect: ネットワーク復帰で再取得refreshInterval: 定期ポーリング(ms)。0で無効
const { data } = useSWR("/api/notifications", { refreshInterval: 10_000 });
依存キーと条件付きフェッチ
キー(第1引数)にnullを渡すとフェッチしません。必要な条件がそろうまで待てます。
function UserDetail({ id }: { id?: number }) {
const { data, error, isLoading } = useSWR(
id ? `/api/users/${id}` : null, // idがないときはフェッチしない
);
// ...
}
キーを配列で表現して、fetcher側で受け取ることもできます。
const fetchUser = (_key: string, id: number) =>
fetch(`/api/users/${id}`).then((r) => r.json());
const { data } = useSWR(["user", 123], fetchUser);
ミューテーションでUIを即時更新
mutateはキャッシュを書き換え、UIを即時反映させる関数です。サーバー反映を待たずに「先に見た目を更新」できます(便利)。
import useSWR, { mutate } from "swr";
function LikeButton({ postId }: { postId: number }) {
const key = `/api/posts/${postId}`;
const { data } = useSWR(key);
const onLike = async () => {
// 楽観的更新(optimistic UI)
mutate(
key,
{ ...data, likes: (data?.likes ?? 0) + 1 },
{ revalidate: false },
);
try {
await fetch(`${key}/like`, { method: "POST" });
// サーバー確定後に再検証
mutate(key);
} catch {
// 失敗したら再検証で正しい値に戻す
mutate(key);
}
};
return <button onClick={onLike}>👍 {data?.likes ?? 0}</button>;
}
やってみよう!
- URLを
/users/2に変えて結果の差を確認 - 同じコンポーネントを2つ置いて、2回目が高速表示(キャッシュ命中)されることを体験
- ネットワークを「Slow 3G」にしてSWRの体験を比較(Chrome DevTools > Network)
refreshInterval: 5000を設定して、一定間隔でデータが更新される様子を確認mutateで「楽観的更新」を体験(いいねボタンなど)- 条件付きフェッチで「フォーム入力完了まで待つ」UIを実装
ポイント(まとめ)
- SWRは「キャッシュ優先+裏で再取得」の戦略
useSWR(key, fetcher)が基本形- 状態(loading/error/data)を内蔵していてUIが簡単
SWRConfigで全体方針を一括設定- フォーカス/再接続/ポーリングで最新化タイミングを制御
mutateでキャッシュを書き換えてUIを即反映nullキーで条件付きフェッチ、配列キーで柔軟に渡す
参考リンク
- SWR 公式 https://swr.vercel.app/ja
- JSONPlaceholder https://jsonplaceholder.typicode.com/