こんにちは、システムエンジニアの Kota です。今回は少し前に発表された SWR ver 2.0 に便利で新しいオプションが追加されたので、簡単に解説したいと思います。
今回追加されたオプション
- optimisticData
- クライアントキャッシュを即座に更新するためのデータ、または現在のデータを受け取り新しいクライアントキャッシュデータを返す関数
- populateCache
- リモートミューテーションの結果をキャッシュに書き込むかどうか、またはリモートミューテーションの結果と現在のデータを引数として受け取り、ミューテーションの結果を返す関数
- rollbackOnError
- リモートミューテーションがエラーだった場合にキャッシュをロールバックするかどうか、または発生したエラーを引数として受け取りロールバックするかどうかの真偽値を返す関数
公式のドキュメントは こちら です。
公式のブログは こちら です。
解説
公式ブログでは、簡単な Todo の追加が例として記載されています。
await addNewTodo('New Item')
addNewTodo
は, Todo リストに新しい Todo を追加するための Promise もしくは、非同期関数で、更新後のデータを返します。
これまでは、Todo が追加された場合、 UI への表示は、 mutate を通してサーバにリクエストを送信し、リモートで最新のデータを取得し、返ってきたレスポンス内のデータを使って UI 側を更新するといった流れでした。
const { mutate, data } = useSWR('/api/todos')
return <>
<ul>{/* データの表示 */}</ul>
<button onClick={async () => {
await addNewTodo('New Item')
mutate()
}}>
Add
</button>
</>
※ 画面は後述する公式の example
問題点
もし仮に await addNewTodo('New Item')
のリクエストで時間が掛かった場合、レスポンスが返ってくるまでの間、更新前の Todo リストが表示されたままの状態になり UX が低下してしまいます。
新オプション
今回 ver 2.0 で登場した新しいオプション optimisticData
でそれを解決できます。
const { mutate, data } = useSWR('/api/todos')
return <>
<ul>{/* データの表示 */}</ul>
<button onClick={() => {
mutate(addNewTodo('New Item'), {
// クライアントキャッシュを即座に更新する
optimisticData: [...data, 'New Item'],
})
}}>
Add
</button>
</>
上記のように optimisticData
オプションを使うことで、サーバからのレスポンスを待つことなく新しい状態のリストを表示できます。data
を optimisticData
の値によって更新し、サーバにリクエストを送信します。リクエストが完了したら SWR はリソースを revalidate しデータが最新であることを保証します。
また、populateCache
オプションを有効にすることで、ミューテーションのレスポンスで useSWR
のキャッシュを更新できます。
const { mutate, data } = useSWR('/api/todos')
return <>
<ul>{/* データの表示 */}</ul>
<button onClick={() => {
mutate(addNewTodo('New Item'), {
optimisticData: [...data, 'New Item'],
// ミューテーションのレスポンスで useSWR のキャッシュを更新
populateCache: true,
})
}}>
Add
</button>
</>
populateCache
オプションを有効にした場合、レスポンスのデータが正しい場合、revalidate
は必要ないので、合わせて無効化します。
const { mutate, data } = useSWR('/api/todos')
return <>
<ul>{/* データの表示 */}</ul>
<button onClick={() => {
mutate(addNewTodo('New Item'), {
optimisticData: [...data, 'New Item'],
populateCache: true,
// populateCache を有効にする場合は、revalidate は不要
revalidate: false,
})
}}>
Add
</button>
</>
addNewTodo
が例外で失敗した場合は、楽観的な更新によるデータがユーザーに表示されます。正しいデータを保証する為に、rollbackOnError
オプションで、optimisticData
のデータを更新前の data
にロールバックします。( default で rollbackOnError=true になっている )
const { mutate, data } = useSWR('/api/todos')
return <>
<ul>{/* データの表示 */}</ul>
<button onClick={() => {
mutate(addNewTodo('New Item'), {
optimisticData: [...data, 'New Item'],
populateCache: true,
revalidate: false,
rollbackOnError: true,
})
}}>
Add
</button>
</>
参考
- 公式の example でオプションの設定を変えてみて、挙動を確認してみて下さい。
まとめ
いかがでしたか? 今回は SWR ver 2.0 で登場した新しいオプションについて解説してみました。なお、本日ご紹介したオプションは同じく 2.0 で登場した useSWRMutation
でも使えるオプションになりますので、合わせてチェックしてみて下さい。