SWR とは
SWR(stale-while-revalidate) は、データ取得のための React Hooks ライブラリで、次の戦略で実装されている。
- キャッシュからデータを返す(stale)
- フェッチリクエストを送る(revalidate)
- 最新のデータを取得する
つまり、SWR を用いることで、コンポーネントはデータの更新を継続的かつ自動的に受け取ることができるようになる:
import useSWR from "swr"; function Profile() { const fetcher = (...args) => fetch(...args).then((res) => res.json()); const { data, error, isLoading } = useSWR("/api/user", fetcher); if (error) return <div>failed to load</div>; if (isLoading) return <div>loading...</div>; return <div>hello {data.name}!</div>; }
useSWR
フックは、 第一引数に『データの一意な識別子(通常、API の URL)』、第二引数に『データを返す任意の非同期関数』を設定する。第二引数には、ネイティブの fetch
や Axios
のようなツールを設定できる。
userSWR
フックの戻り値の data
, error
, isLoading
からリクエストの状態("loading", "ready", "error") を判断し、対応する UI を返すことができる。
useSWR の API
API は次の構成になっている:
const { data, error, isLoading, isValidating, mutate } = useSWR( key, fetcher, options );
引数
データ名 説明 key
リクエストのためのユニークなキー文字列(関数、配列、 null
も可)fetcher
データをフェッチするための Promise
を返す関数options
SWR の細かい設定を行うためのパラメータ。再検証の設定や通信諸設定、リクエスト後のコールバックなど設定できる。詳細 返り値
データ名 説明 data
fetcher
によって解決された、key
のデータ(ロードされてない場合undefined
)error
fetcher
によって例外が投げられた際にキャッチされたデータisLoading
実行中のリクエストが存在し『ロードされたデータがない』状態 isValidating
リクエスト、または再検証の読み込みがある状態 mutate(data?,options?)
キャッシュされたデータを更新する関数
コンテキストとして SWR を使う
SWR ではコンテキストとしてデータをグローバルに扱えるようにするために SWRConfig
コンテキストが用意されている:
<SWRConfig value={options}> <Component /> </SWRConfig>
value
には、useSWR
の引数の option
パラメータを設定できる:
import useSWR, { SWRConfig } from "swr"; function Dashboard() { const { data: events } = useSWR("/api/events"); const { data: user } = useSWR("/api/user", { refreshInterval: 0 }); // SWRConfig の設定をオーバーライド // ... } function App() { return ( <SWRConfig value={{ refreshInterval: 3000, fetcher: (resource, init) => fetch(resource, init).then((res) => res.json()), }} > <Dashboard /> </SWRConfig> ); }
上記は、全ての SWR フックを同じフェッチャーを用いて更新するように設定している。
関数として利用する
useSWR
で SWR を定義しない方法もある:
import { SWRConfig, useSWRConfig } from "swr"; function App() { return ( <SWRConfig value={{ refreshInterval: 100, fallback: { a: 1, b: 1 }, }} > <Page /> </SWRConfig> ); } function Page() { const config = useSWRConfig(); }
上記は、コンテキストとして SWR を子コンポーネントに渡している。useSWRConfig
は、グローバル設定(コンテキスト)および、ミューテーション、キャッシュを取得している。
自動再検証
自動再検証に関して次のようなオプションがある:
オプション | 説明 | デフォルト値 |
---|---|---|
revalidateOnFocus |
ページ時にフォーカスを合わせるか、タブを切り替えると自動的にデータを再検証する(参考) | 有効 |
refreshInterval |
画面上に表示されているフックに関連づけられたコンポーネントを時間の経過とともに更新する(参考) | 無効 |
refreshWhenHidden |
ウィンドウが非常時の時にポーリングする | 無効 |
refreshWhenOffline |
ブラウザがオフラインの時にポーリングする | 無効 |
revalidateOnReconnect |
ネットワークが回復したときに再検証する | 有効 |
revalidateOnMount |
コンポーネントのマウント時に再検証する | 未定義 |
revalidateIfStale |
古いデータがある場合でも再検証する | 有効 |
条件付きフェッチ
条件付きでデータを取得する場合には、key
(第一引数)に null
か関数を設定する。関数がスローまたは偽値を返した場合、SWR はリクエストを開始しない:
// 条件付きでフェッチする const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher) // user.id が定義されてない場合にスローする const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
引数
デフォルトでは、key
は fetcher
に渡される。下記の式は同じ:
useSWR('/api/user', () => fetcher('/api/user')) useSWR('/api/user', url => fetcher(url)) useSWR('/api/user', fetcher)
複数の引数を渡したい場合は、次のように指定する:
const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
オブジェクトを渡すこともできる:
const { data: user } = useSWR(['/api/user', token], fetchWithToken) // 上で設定した user を使用する const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)