📦
SWRでリスト系のAPIの結果から個別のキャッシュも作る
背景
以下のようなAPIがあるとして、
-
GET /api/user/:user_id
特定のユーザを返す -
GET /api/user
ユーザの一覧をページングして返す (offset, limit)
クライアントアプリでリストAPIのレスポンスをユーザ単体のキャッシュとしても機能させたい。
これを SWRを使いながらやろうという話です。
あ。今回は suspense してないです。
キーワード
実際のコード
- SWRに慣れてるひとは このPR
- ついでにSWRのことも知りたいという人は このリポジトリのPRを古い方から順に見てもらうといいかも。
- コード全体はこちら https://github.com/umezo/example-use-swr
- テストコードもあります
リストAPIの結果から単体のキャッシュを作る
mutate
のラッパーを作る
まずは剥き出しの mutate
をラップしてuseSWRのキーを隠蔽します。
["/api/user/:userId", user.id]
の部分が useSWR
の第一引数と一貫する必要があるからです。
const useMutateUser = () => {
const { mutate } = useSWRConfig();
return React.useCallback(
(user: User) => {
// この第一引数を外に出したくない
mutate(["/api/user/:userId", user.id], user, { revalidate: false });
},
[mutate]
);
}
const useUser = (userId: User['id']) => {
return useSWR(
["/api/user/:userId", userId],
...
);
}
副作用として個別キャッシュを作る
あとは副作用としてページの結果を返す前にキャッシュを作るだけです。
// キャッシュ用のインターフェースを持ってきて
const mutateUser = useMutateUser();
useSWRInfinite(
...,
async (...) => {
// response = {list: User[]}
const response = await fetchUsers(...);
// 使うだけ
response.list.forEach(mutateUser);
return response;
},
);
まとめ
「useSWRInfinite
から useSWR
のキャッシュを mutate
をつかって作る。」という話でした。
テストのための msw
のハンドラーの実装についても触れようかと思ってたんですが長くなるのでやめました。
別記事にしようかと思っていますが、資料に実装済みのものがあります。
Discussion