SWRのfetcherをジェネリクスを使って共通化
取得するデータがUserだろうがBlogだろうが、処理は一緒なのでfetcherは共通化できるはず。
ところがTypeScriptの場合、取得できるデータやクエリパラメーターなどの型がそれぞれ異なってしまう。 fetcherとなるfetchData関数をこんなふうに書く。
code: typeScript
import axios from 'axios';
// paramsはオプションなので、paramsに割り当てるU型もオプション扱いにする
export const fetchData = async <T, U = undefined>(
url: string,
options: {
id?: string;
params?: U;
}
): Promise<T> => {
const { params, id } = options;
// 例外処理はここでは省略
const { data } = await axios.get<T>(
id === undefined ? url : ${url}/${id}, { params }
);
return data;
};
呼び出し側はこうなる。
code: typescript
import useSWR from 'swr';
import { User, UserApiParams } from 'domains';
// idに紐づくユーザーを取得
// - fetchDataのT部分にUser型を指定
// - fetchDataのU部分は省略
const { data: user } = useSWR(
async (url, id) => await fetchData<User>(url, { id }) );
// 名前に一致する複数のユーザーを取得(条件付きフェッチ)
// - fetchDataのT部分にUser[]型を指定、複数返ってくる想定なのでArray
// - fetchDataのU部分はUserApiParams型(パラメーターの型)を指定
const { data: users } = useSWR(
nameLike
: null,
await fetchData<User[], UsersApiParams>(url, { params })
);