はじめに
最近、React用ライブラリのSWRを触る機会があったので備忘録的に内容について書きたいと思います。
概要
Next.jsを作成しているVercel製のデータフェッチ用ライブラリ。
APIでのデータ取得、キャッシュ管理、状態管理など一通り行なってくれます。
公式に
“SWR” という名前は、 HTTP RFC 5861(opens in a new tab) で提唱された HTTP キャッシュ無効化戦略である stale-while-revalidate に由来しています。 SWR は、まずキャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという戦略です。
とあるように、
・APIで取得したデータをキャッシュする
・次回同じAPIにアクセスする際にはキャッシュを返す
・バックグラウンドでデータの更新があるかを検証し、更新があれば自動でキャッシュの更新を行う
・結果として無駄なAPIアクセスを行わず高パフォーマンスな挙動を簡単に実現出来る
の様な特徴があります。
使い方
基本的な使い方を見てみましょう
1 2 3 4 5 6 7 8 9 10 11 | import axios from 'axios' const fetcher = url => axios.get(url).then(res => res.data) function App () { const { data, error } = useSWR('/api/data', fetcher) if (!data) return 'loading...' if (error) return 'error...' {data.body} } |
引数はそれぞれ
・第1引数:このリクエストのためのユニークなキー文字列。このキーを元に取得結果がキャッシュされるようです。通常はAPIのエンドポイントみたいです。
・第2引数:データをフェッチするための Promise を返す関数。今回はAxiosを使用しています。fetchでも良いみたいです。
となっていて、返却値の
data
にデータ取得前やエラー時は
undefined
が入り、データ取得後のタイミングでfetch関数の戻り値が入ります。
そのため、
data
の値をif条件に表示/非表示を切り替える事も可能です。
主な特徴
useSWRには公式にある通り様々な特徴がありますが、特に重要だと思うのは以下3点です。
自動再検証
データ取得後はキャッシュされた値が返却されますが、キャッシュされた値の再検証を自動で行う事が出来ます。
APIを再フェッチして結果に差分があればキャッシュが自動で即更新されます。
この更新方法はいくつか種類があり、それぞれ第3引数のoptionの中で設定する事が出来ます。
1 2 3 4 5 | const { data, error } = useSWR('/api/data', fetcher, { refreshInterval: 1000 // ミリ秒単位。1秒毎に再検証。ポーリング機能として使える revalidateOnFocus: true // ウィンドウがフォーカスされたときに再検証 revalidateOnReconnect: true // ブラウザがネットワーク接続を回復するときに再検証 }) |
逆に自動再検証が不要な場合は、以下のフックを使えます。
1 2 3 4 | import useSWRImmutable from 'swr/immutable' // ... useSWRImmutable(key, fetcher, options) |
重複排除
同じフェッチ内容であれば、複数箇所で使用しても実際にリクエストされるのは1回のみとなる
例えば、以下の様にuseSWRを内包したコンポーネントを複数使用してもリクエスト1回のみです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function useUser () { return useSWR('/api/user', fetcher) } function Avatar () { const { data, error } = useUser() if (error) return <Error /> if (!data) return <Spinner /> return <img src={data.avatar_url} /> } function App () { return <> <Avatar /> <Avatar /> <Avatar /> <Avatar /> <Avatar /> </> } |
ステート管理
useSWRは、
data
、
error
の他に、
isLoading
と
isValidating
の値を返却します。
各値はAPI通信状況によって更新されるので、各ステート管理に非常に便利です。
1 2 3 4 5 6 7 | const { data, error, isLoading, isValidating } = useSWR('/api/data', fetcher) // console.log(data, error, isLoading, isValidating) undefined undefined true true // => フェッチの開始 undefined Error false false // => フェッチの完了、エラーを取得 undefined Error false true // => 再試行の開始 Data undefined false false // => 再試行の完了、データを取得 |
1点注意点があり、上記の様に4つの値が更新される状況だと、コンポーネントが4回レンダリングされる事になるようなので
必要な値のみ使用して不要なレンダリング回数が増えない様にした方が良いみたいです
さいごに
APIでのデータ取得周りを一通りカバーしてくれるのは有り難いですね。次回はuseSWRで無限スクロールの実装をしてみたいと思います。