🍣

SWRで複数の引数を渡して使う方法

2024/01/09に公開

SWR、便利ですよね。SWRはデータ取得のためのReact Hooksライブラリです。

SWR は、まずキャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという戦略です。

SWRを使うことでコードをシンプルにし、かつサーバーからのデータ取得乱発を避けることができます。例えばaxiosを使ってデータを取得する場合、コードはこうなります。

fetch
const fetchData = async () => {
  try {
    const response = await fetch(
      `https://xxx.../v1/data`,
        {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });
      const data = await response.json();
      
    } catch (error) {
      console.error('読み込みに失敗しました。', error);
    }
  };
fetchData();

tokenを渡して認証を通し、データを受け取っています。

これを実装した場合、コンポーネントが読み込まれるたびにサーバーと通信を行い、データを取得することになります。

SWRを使うと

swr_sample
import useSWR from 'swr'
 
function Profile() {
  const { data, error, isLoading } = useSWR('https://xxx.../v1/data', fetcher)
 
  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

公式コードにある通り、これだけのコードで済むようになり、見通しもよくなります。
(tokenを渡してないので実際には動きません、後半で実際に動くコードをのせています)

useSWRの第一引数はkeyです。このkeyは保存ファイル名みたいなもので、このkey名でデータをキャッシュし、またキャッシュがあるかどうかを調べます。

第二引数は関数です。この関数を動かしてデータを取得してきます。かんたんなfetcher関数はこのように定義できます。

fetcher
const fetcher = (...args) => fetch(...args).then(res => res.json())

では最初のコードのようにtokenなどの引数を渡したい場合はどうすればいいでしょうか。

SWR_sample
const shouldFetch = (token) => !!token;
const { data: currentData } = useSWR(shouldFetch(token) ? ['/v1/data', token] : null, ([url, token]) => fetchCurrentData(url, token))

まず、tokenがある場合にのみデータを返すようにしています。

第一引数には['/v1/data', token]としており、このように複数の引数を配列で渡すことができます。つぎにtokenが存在するタイミングでfetchCurrentDataが実行され、第一引数として['/v1/data', token]が渡されます。次にURLとtokenを引数としてデータを取得しています。

呼び出されるfetchを行う関数はこのようになっています。

fetch_sample
import { fetcher } from "@/api/fetcher";

export const fetchCurrentData = async (url: string, token: string) => {
  const response = await fetcher({
    url: `${url}`,
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
  });
  return response;
};

データを取得したタイミングでデータをセットしたい場合はuseEffectを使います。

const [currentData, setCurrentData] = useState(null);

  useEffect(() => {
    if (currentData) {
      setTeamList(currentData);
    }
  }, [currentData, setCurrentData]);

SWRはお手軽で便利なHookなので積極的に使っていきたいところです。

Discussion