このページ内容は2021年1月21日以降、再調査・再検証してません。実際に扱う際は最新の情報にアクセスしてください。
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に値が入ります。
1import React from "react";2import useSWR from "swr";34const fetcher = (url) => fetch(url).then((res) => res.json());5// axiosを使いたい場合6//const fetcher = url => axios.get(url).then(res => res.data)78export default function App() {9const { data, error } = useSWR(10"https://api.github.com/repos/vercel/swr",11fetcher12);1314if (error) return "An error has occurred.";15if (!data) return "Loading...";16return (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。
1function useUser (id) {2const { data, error } = useSWR(`/api/user/${id}`, fetcher)34return { user: data, isLoading: !error && !data, isError: error }5}
1function Avatar ({ id }) {2const { user, isLoading, isError } = useUser(id)34if (isLoading) return <Spinner />5if (isError) return <Error />6return <img src={user.avatar} />7}
ちなみにデータを再検証するタイミングも制御でき、定期的に実行したい場合はrefreshInterval, ウィンドウが非表示のときにポーリングしたいならrefreshWhenHidden, ネットワークがオフラインのときにポーリングしたいならrefreshWhenOfflineなどのオプションを付けて制御できるそうですswr_revalidation_offline。
1useSWR('/api/todos', fetcher, { refreshInterval: 1000 })
また、useSWRImmutableを使うことで、1度しかリクエスト結果を検証しないように使うこともできますswr_revalidation_immutable。
1import useSWRImmutable from 'swr/immutable'23// ...4useSWRImmutable(key, fetcher, options)
レスポンスでエラーが返ってきたときのデータの再取得方法も指定でき、再試行しないステータスや試行回数、試行間隔なども指定できますswr_error_handling。
1useSWR('/api/user', fetcher, {2onErrorRetry: (error, key, config, revalidate, { retryCount }) => {3if (error.status === 404) return // 404では再試行しない。45if (key === '/api/user') return // 特定のキーでは再試行しない。67if (retryCount >= 10) return // 再試行は10回までしか再試行しない。89setTimeout(() => revalidate({ retryCount }), 5000) // 5秒後に再試行する。10}11})