マウント時のSWRキャッシュ更新処理の制御
SWRを使用している際に、オプションの設定誤りでマウント時のキャッシュ更新処理が意図しない動きをすることがありました。キャッシュデータの有無によって意図しないリクエストが飛んでしまうため、オプションを適切に設定しておきたいところです。公式ドキュメントはこの辺が少し分かりづらいため共有したいと思います。
マウント時の更新処理に関わるオプション
マウント時のキャッシュ更新処理を制御するオプションは以下の2つです。
revalidateOnMount
revalidateIfStale
これらの設定値の組み合わせで動作が変わるので詳しく見ていきます。
revalidateOnMount
revalidateOnMount
オプションは、マウント時に再検証を行うかどうかを設定します。
-
true
: 再検証を常に行う -
false
: 再検証を常に行わない
このオプションだけでマウント時の制御が決まりそうですが、上記オプションはデフォルトでは未設定となっています。その場合は次のrevalidateIfStale
によって制御されます。
revalidateIfStale
revalidateIfStale
オプションは、既にキャッシュデータが存在している場合に再検証するか否かを決定します。
-
true
(デフォルト): キャッシュデータがあっても更新を行う -
false
: キャッシュデータがあれば更新を行わない
つまり、これらのデフォルト状態のオプションは場合、revalidateOnMount
:未設定, revalidateIfStale
:true
なので、マウント時には必ず再検証が行われます。
制御ケース
以上を踏まえてそれぞれの制御ケースをこれらの組み合わせで考えたいと思います。
どんなときもマウント時は再検証しない
useSWR('/api/data', fetcher, { revalidateOnMount: false })
revalidateOnMount
をfalse
としているので、revalidateIfStale
の設定に関わらずマウント時の再検証は発生しなくなります。
上記は、mutate
APIなどで再検証タイミングを制御したい場合に利用できます。
マウント時は必ず再検証する
useSWR('/api/data', fetcher, { revalidateOnMount: true })
// or
useSWR('/api/data', fetcher, { revalidateOnMount: undefined, revalidateIfStale: true })
// or
useSWR('/api/data', fetcher, { revalidateIfStale: true }) // デフォルト
上記はどれもマウント時は常に再検証される設定になります。
ただし、{ revalidateIfStale: true }
の場合revalidateOnMount
が未設定のため、他のSWR設定やグローバル設定によって上書きされる可能性があることに注意が必要です。
function MyComponent() {
const { data, error } = useSWR('/api/data', fetcher, { revalidateIfStale: true })
// ...
}
function App() {
return (
<SWRConfig
value={{
revalidateOnMount: false, // グローバル設定でマウント時の再検証を無効にする
}}
>
<MyComponent />
// ...
</SWRConfig>
)
}
キャッシュデータが存在していない場合だけ再検証する
useSWR('/api/data', fetcher, { revalidateIfStale: false })
revalidateOnMount
は設定せず、revalidateIfStale
をfalse
としているので、revalidateIfStale
の設定に関わらずマウント時の再検証は発生しなくなります。
ただし、こちらもrevalidateOnMount
を明示的に設定していないのでグローバル設定によって上書きされる可能性があります。上書きを防止したい場合は上記と同様に明示的にrevalidateOnMount: undefined
とする必要があることに注意してください。
まとめ
SWRはキャッシュ制御を便利してくれますが、オプションが豊富で再検証を自動で行うなど意図せず検証処理が走ることがあります。効率的なデータ取得とパフォーマンスの最適化を実現するために適切にSWRの設定を行うとよいかと思います。
Discussion