SWRを扱う上で躓いたところを共有し誰かの参考になればと思い、記事にしました。
SWRの使い方の記事ではなく、SWRを知っている前提の内容です。
公式 https://swr.vercel.app/ja
やりたいこと
楽観的UI更新(optimistic update)
楽観的更新とは、ユーザーが行った操作をサーバーからのレスポンスを待たずにUIに反映する手法のことです。
公式のソースコードはこのようになっています。
import useSWR, { useSWRConfig } from 'swr'
function Profile () {
const { mutate } = useSWRConfig()
const { data } = useSWR('/api/user', fetcher)
return (
<div>
<h1>My name is {data.name}.</h1>
<button onClick={async () => {
const newName = data.name.toUpperCase()
const user = { ...data, name: newName }
const options = {
optimisticData: user,
rollbackOnError(error) {
// タイムアウトの AbortError だった場合はロールバックしません
return error.name !== 'AbortError'
},
}
// ローカルのデータを即座に更新します
// データを更新するためにリクエストを送信します
// ローカルデータが正しいことを保証するために再検証 (再フェッチ) を発行します
mutate('/api/user', updateFn(user), options);
}}>Uppercase my name!</button>
</div>
)
}
ソースコード下部mutate('/api/user', updateFn(user), options)
の updateFn(user)
は
このソースコードにはないですがPromiseか非同期関数であり、更新後のデータを返します。
サーバからのレスポンスを待たずに<h1>My name is {data.name}.</h1>
のdataをoptimisticData
の値で更新しています。
躓いたところ
optimisticDataの値でUIが更新されない。
結論
updateFn(user)
の戻り値は、「指定されたキーのデータの型」と一致している必要があるようです。
この場合mutateのkeyは'/api/user'で、 const { data } = useSWR('/api/user', fetcher)
のdataの型と一致している必要があります。
※私の場合はいいね機能を実装していて、dataはユーザ情報を持つ型でした。いいね更新APIの戻り値はPromise<boolean>
としていたためうまくいきませんでした。