このページ内容は2021年1月21日以降、再調査・再検証してません。実際に扱う際は最新の情報にアクセスしてください。

link
SWR 1.0

SWRはNext.jsで有名なVercelが提供しているReact Hooksライブラリで、fetchやaxios, graphql-requestなどのデータを返す非同期関数と併用し、フロントで取得したデータを再利用可能な形にできるものですswr

SWRはstale-while-revalidateの頭文字を取って名付けられており、キャッシュからデータを返し (stale)、次にフェッチリクエストを送り (revalidate)、最後に最新のデータを取ってくるというのを基本戦略としています。そのため、キャッシュの扱いやリクエストの実行タイミングに関してよく考えられています。

SWRは以下のような形式で扱うことができます。まずfetcherとして、SWRと併用したいデータフェッチライブラリの設定をします。次にuseSWRを使って、レスポンス先とfetcherを指定し、その返り値としてdataとerrorを取るようにして使います。リクエストが返るまでの間はdataとerrorはundefinedになり、値が返るとdataに、エラーが返されるとerrorに値が入ります。

1
import React from "react";
2
import useSWR from "swr";
3
4
const fetcher = (url) => fetch(url).then((res) => res.json());
5
// axiosを使いたい場合
6
//const fetcher = url => axios.get(url).then(res => res.data)
7
8
export default function App() {
9
const { data, error } = useSWR(
10
"https://api.github.com/repos/vercel/swr",
11
fetcher
12
);
13
14
if (error) return "An error has occurred.";
15
if (!data) return "Loading...";
16
return (
17
<div>
18
<h1>{data.name}</h1>
19
<p>{data.description}</p>
20
<strong>👁 {data.subscribers_count}</strong>{" "}
21
<strong>{data.stargazers_count}</strong>{" "}
22
<strong>🍴 {data.forks_count}</strong>
23
</div>
24
);
25
}

SWRでは以下のようなコンポーネントを作っておくと、他の場所でもリクエスト結果を使い回すことができます。複数のコンポーネントで使うと、使いまわした回数だけリクエストが実行されそうですが、SWRではキャッシュを使い、リクエストを1度だけしか実行しないようです (フェッチリクエストの動きを把握してないため、少し濁して説明してます)。

また、デフォルトで「ページにフォーカスが当たる」「タブを切り替える」「ネットワークがオフラインからオンラインに回復する」ときにデータの再検証をしてくれるそうですswr_revalidation

1
function useUser (id) {
2
const { data, error } = useSWR(`/api/user/${id}`, fetcher)
3
4
return { user: data, isLoading: !error && !data, isError: error }
5
}
1
function Avatar ({ id }) {
2
const { user, isLoading, isError } = useUser(id)
3
4
if (isLoading) return <Spinner />
5
if (isError) return <Error />
6
return <img src={user.avatar} />
7
}

ちなみにデータを再検証するタイミングも制御でき、定期的に実行したい場合はrefreshInterval, ウィンドウが非表示のときにポーリングしたいならrefreshWhenHidden, ネットワークがオフラインのときにポーリングしたいならrefreshWhenOfflineなどのオプションを付けて制御できるそうですswr_revalidation_offline

1
useSWR('/api/todos', fetcher, { refreshInterval: 1000 })

また、useSWRImmutableを使うことで、1度しかリクエスト結果を検証しないように使うこともできますswr_revalidation_immutable

1
import useSWRImmutable from 'swr/immutable'
2
3
// ...
4
useSWRImmutable(key, fetcher, options)

レスポンスでエラーが返ってきたときのデータの再取得方法も指定でき、再試行しないステータスや試行回数、試行間隔なども指定できますswr_error_handling

1
useSWR('/api/user', fetcher, {
2
onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
3
if (error.status === 404) return // 404では再試行しない。
4
5
if (key === '/api/user') return // 特定のキーでは再試行しない。
6
7
if (retryCount >= 10) return // 再試行は10回までしか再試行しない。
8
9
setTimeout(() => revalidate({ retryCount }), 5000) // 5秒後に再試行する。
10
}
11
})

自己紹介
はじめまして Pilefortです。
東京でエソジニアをしてます。
興味のあるスタックは、JavaScript (React, Vue), TypeScript, Rust, WebAssembly, AWS, Pulumi, Serverless Frameworkです。
このブログでは、普段の業務や趣味で気になったことをまとめたり、フロントやAWS, GitHubやTwitterで見かけた面白い記事やニュースをまとめるためのものです。少しでも何かの役に立てば幸いです。
サイトマップ
Notes
業務や趣味での気づき・メモ
Snippets
記事にするまでもないけど、便利なコマンドや豆知識
Works
同人誌一覧