😸

SWRのfetcher関数を、TypeScriptのGenericsを使っていい感じにする

2023/07/17に公開

備忘録です。

ReactやNext.jsでfetchを利用するときに、選択肢の1つとして上がるSWRですが、最初使ったときにはuseSWRの 第二引数である、fetcher関数がよくわかりませんでした。

import useSWR from 'swr'
 
function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher) // ← なにこれ?
 
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

この記事を見ると、fetcher関数を自分なりにカスタマイズしていくことで、様々なライブラリを利用したり、様々なインターフェースに対応できることがわかります。
https://swr.vercel.app/ja/docs/data-fetching

一旦私はaxiosでSWRを動かしてみようと試みて、色々試行錯誤した結果、以下のようにGenericsを使っていい感じにできました。

'use client'
import useSWR from 'swr'
import axios, { AxiosResponse } from "axios"

export default function Page() {
  type user = {
    ID: string,
    name: string,
    email: string,
  }

  const fetcher = <T,>(path: string): Promise<T> => axios.get("http://localhost:8080" + path).then((res: AxiosResponse<T>) => res.data)
  const { data, error, isLoading } = useSWR<user[]>('/users', fetcher)
 
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {data && data.map((user: user) => (
          <li key={user.ID}>
            <span>{user.name}</span>
            <span>{user.email}</span>
          </li>
        ))}
      </ul>
    </div>
  )
}

fetcher関数にGenericsを利用することで、様々な箇所で汎用的に使えるfetcher関数になりました。
APIのホストも統一されるので、利用側としては pathだけを気にすればいいのでいい感じです。

Discussion