TL;DR
SWR wrapper
import useSWR, { BareFetcher } from 'swr'
import { PublicConfiguration } from 'swr/dist/types'
import { buildApiClient } from '@/lib/apiClient'
type AxiosOptions = {
baseUrl?: string
}
const useCustomSWR = <Data>(
key: string,
bareFetcher: BareFetcher<Data> | undefined | null = undefined,
config: Partial<PublicConfiguration<Data, any, BareFetcher<Data>>> | undefined = undefined,
axiosOptions: AxiosOptions = {},
) => {
const fetcher = getFetcher<Data>(bareFetcher, axiosOptions)
return useSWR<Data>(key, fetcher, config)
}
const getFetcher = <Data>(
fetcher: BareFetcher<Data> | null | undefined,
axiosOptions: AxiosOptions = {},
) => {
if (fetcher === undefined) {
const apiClient = buildApiClient(axiosOptions)
return (url: string) => apiClient.get(url).then((r) => r.data)
}
return fetcher
}
export default useCustomSWR
Axios wrapper
import axios from 'axios'
type Props = {
baseUrl?: string
headers?: {}
}
export const buildApiClient = ({ baseUrl = 'http://localhost:8080', headers = {} }: Props) => {
const customHeaders = { ...headers, ...{ 'Content-Type': 'application/json' } }
const apiClient = axios.create({
baseURL: baseUrl,
responseType: 'json',
headers: customHeaders,
})
apiClient.interceptors.request.use(
(config) => {
console.log(config)
return config
},
(error) => {
console.error(error)
return Promise.reject(error)
},
)
apiClient.interceptors.response.use(
(response) => {
console.log(response)
return response
},
(error) => {
switch (error.response?.status) {
case 400:
case 401:
break
default:
console.error(error)
}
},
)
return apiClient
}
ざっくりSWRとは
データ取得のための React Hooks ライブラリです。
以下のような特徴があり、シンプルかつ高機能なデータ取得から取得データのステート管理までをまるっと行ってくれます。
ref: swr.vercel.app
- 速い、 軽量 そして 再利用可能 なデータの取得
- 組み込みの キャッシュ とリクエストの重複排除
- リアルタイム な体験
- トランスポートとプロトコルにとらわれない
- SSR / ISR / SSG support
- TypeScript 対応
- React Native
SWRにはglobal configが提供されており、こちらを使用することでuseSWR
の処理をカスタマイズすることができますが呼び出し元によって設定をカスタマイズしたいユースケースを考えwrapperを作成し利便性を上げてみました。
使い方
データ取得で使う
import useCustomSWR from '@/lib/useCustomSWR'
type Data = {
data: { code: number; name: string }[]
}
const useFetchData = () => {
const { data, error } = useCustomSWR<Data>('/api_endpoint')
return {
data,
isLoading: !error && !data,
isError: error,
}
}
export default useFetchData
<Data>
のようにtypeを渡すことで返却される data
のtypeを定義できるのがポイントです。
APIリクエストしないステート管理で用いる
SWRは第二引数のfetcherにnullを渡すとAPIリクエストをしないようにできるのがポイントです。これとSWRによって提供されているmutate
という関数を用いてグローバルステート管理に使えます。
ref: SWRはローカルの状態管理としても使える
import useCustomSWR from '@/lib/useCustomSWR'
const useGlobalNotification= () => {
const { data: message, mutate: setMessage } = useCustomSWR<string>(
'notification',
null,
{
fallbackData: "",
},
)
return {
message,
setMessage
}
}
export default useGlobalNotification
一つ目の引数にはglobalStateのkeyとなる文字列を渡し、二つ目のfetcherにnull、三つ目のoptionsにはfallbackDataを渡すことによりデフォルトのステートの値を定義できます。
keyはユニークでないといけないので実際にはenumなどを用いて一つのファイルで定義しておくと良いでしょう。
こちらを各コンポーネントで呼びsetMessageを用いてmessageステートを変更することでmessageステートの参照コンポーネントにレンダリングが走ります。
まとめ
Reactのステート管理ツールには他にもrecoil, react-queryなどがありますが個人的にはSWRがシンプルかつパワフルな機能を提供していてオススメです!試したことない方は是非使ってみてください!