初めに
Reactを書いていると、
「ユーザー情報を取得してUIに反映する」みたいなデータ表示処理ってよくありますよね。
実務でも「とりあえず useSWR 使っとけばいい感じにデータ取れる」みたいなノリでなんとなく使っている人、多いと思います。私もそうです。
でも実は、SWRがどこを見て・いつデータを取りにいってるのかを正しく理解している人は意外と少ないと思います。
この記事では、
「SWRって変更を検知して更新してるってよく言うけど、実際どうやってるの?」
という疑問を、ユーザー情報の取得を例に解説します。
SWRとは?
SWRは、データ取得(fetch)とキャッシュ管理を賢くやってくれるReact Hooksベースのライブラリです。Vercel(Next.jsの会社)が開発しており、名前の由来は「Stale-While-Revalidate」 というHTTPキャッシュ戦略からきています。
useSWRってどう動いてるの?
たとえば、以下のようにユーザー情報を取得するコード
import useSWR from 'swr'
const fetcher = (url: string) => fetch(url).then(res => res.json())
export default function UserInfo() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (isLoading) return <p>Loading...</p>
if (error) return <p>Failed to load</p>
return <div>Welcome back, {data.name}!</div>
}
これだけで、
- キャッシュされたデータを即座に返す(高速表示)
- 裏で新しいデータを再フェッチ
- タブ復帰やネット復帰でも自動で再フェッチ
- 重複リクエストを防ぐ
という挙動を自動でやってくれます。
便利すぎますね!
でも、「どこを見て更新してるのか」までは意識せず使ってる人が多いと思います。
勘違いしやすい点①:「SWRは変更を監視している」ではない
SWRの「変更検知」はリアルタイム監視ではありません。
よく「SWRってサーバー側の変更を勝手に検知して更新してくれるんでしょ?」と勘違いされますが、実際そうではありません。
SWRがやっているのはあくまで「再フェッチを行うタイミング管理」です。
イベント | SWRの挙動 |
---|---|
ページを開く | 一度fetchしてキャッシュ |
タブを戻る(フォーカス復帰) | もう一度fetchして最新を取得 |
ネットが復帰 | 再fetch |
mutate(key) を呼ぶ | 強制再fetch |
refreshInterval が経過 | 定期再fetch |
この“再フェッチ”の結果が前回と違えば、UIが更新される — これがSWRの「変更検知」の正体です。
勘違いしやすい点②:パフォーマンスが上がる? → 体感速度が上がるだけ!
これも誤解しやすいポイントです。
SWRは通信そのものを速くしているわけではありません。
実際には同じAPIを同じ回数fetchしています。
でも、キャッシュを先に描画するから“速く見える”。
つまり「パフォーマンス(処理速度)」ではなく
「UX(体感スピード)」を上げているんです。
- 通信回数:変わらない
- APIレスポンス:同じ
でも
- 体感は「即時表示」
というのがSWRの挙動です。
勘違いしやすい点③:APIは“変更があった時だけ”叩いてるわけじゃない
ここもよく誤解されます。
SWRは「変更があったらAPIを叩く」ではなく、
「タイミングが来たら毎回APIを叩く」 です。
たとえば /api/user を取得している場合:
const { data } = useSWR('/api/user', fetcher)
SWRは内部的にこんなキャッシュを持っています👇
const cache = { '/api/user': { data: oldData, timestamp: 1696740000 } }
async function revalidate() {
const newData = await fetcher('/api/user') // ← 毎回fetch!
if (JSON.stringify(newData) !== JSON.stringify(cache['/api/user'].data)) {
cache['/api/user'].data = newData
rerender() // 再描画トリガー
}
}
つまり、サーバー側の変更があったかどうかに関係なく fetcher は必ず実行されます。
SWRは「fetch結果が前と違うか」を見て初めてUIを更新しています。
変更を検知しているのではなく、再フェッチ結果の差分を見ているだけなんです。
では何を見て変更を判断しているの?
SWRは キー(key)とキャッシュ を基準に動きます。
const { data } = useSWR('/api/user', fetcher)
/api/user がkeyです。
SWRはこのkeyごとにキャッシュを保持し、イベント発火時(focus, online, mutateなど)に再フェッチして、キャッシュの中身とfetch結果を比較します。
違っていればキャッシュを更新 → React再レンダー。
これがSWRの「変更検知」です。
変更(再フェッチ)が起こるタイミング
繰り返しになるのですが、再フェッチのタイミングをまとめておきます。
タイミング | 動作 |
---|---|
初回レンダー |
fetcher 実行 |
key 変更 |
新しいデータをfetch |
タブ復帰 | 再fetch |
ネット復帰 | 再fetch |
mutate() |
手動fetch またはキャッシュ更新 |
refreshInterval 設定 |
定期的にfetch |
まとめ
- SWRはサーバーの変更を監視しているのではなく、キャッシュとfetch結果の差分を見てUIを更新している。
- key(キャッシュキー)ごとに前回のデータを保持し、再フェッチ時に新しいデータと比較して差分があれば再描画する。
- APIは「変更があった時だけ」呼ばれるわけではなく、指定されたタイミング(focus復帰・mutate・intervalなど)ごとに毎回fetchしている。
- 通信速度自体は変わらないが、キャッシュを即時表示しつつ裏で更新することでUXが速く感じられる。
- 結果として、キャッシュ管理・再フェッチ制御・データ鮮度維持を自動化でき、実務での開発効率とユーザー体験を大きく改善できる。