📚
Suspenseコンポーネント, SWRライブラリを利用したAPIデータ取得
はじめに
- Suspenseコンポーネントを利用し、SWRライブラリ経由でデータ取得、その取得結果をコンポーネントへ表示。まずは基本動作。
- SWRライブラリはVercel社作成ライブラリで、詳細は他の記事が詳しい。
- Suspenseタグ内部のコンポーネントのローディングが完了していない場合、propsのfallbackの内容を表示する。
- Suspenseタグ内部のコンポーネントは複数指定が可能。API1, API2, API3を呼び出すコンポーネントを内部に指定し、すべてのデータ取得が完了するまで、fallbackの内容が表示される。
- useQueryの返り値isLoadingにより出力を変える書き方等より、シンプルで可読性のある記載が可能となる。
SWRライブラリによるARI呼び出し ./src/components/hooks/useAllUsersSWR.ts(カスタムフック)
- useSWR
- 1番目引数(key): APIを指定、ここではJSONPlaceholderのUsersAPI呼び出し。
- 2番目引数(fetcher): データをフェッチし、Promiseを返す関数を指定。
- 非同期処理 asyncの戻り値の型はPromiseであるべきだが、実際の戻り値はJSONに変換することは可能。The fetcher here is an async function that accepts the key of SWR, and returns the data.
- 3番目引数(option): オプション指定。この部分に{ suspense: true }を指定する。
- useSWRで取得するデータの戻り値の型を指定。
import useSWR from "swr";
import { User } from "../types/User";
export const useAllUsersSWR = () => {
const fetcher = async (url: string): Promise<any> => {
const resonse = await fetch(url);
return resonse.json();
};
const { data, error } = useSWR<Array<User>>(
"https://jsonplaceholder.typicode.com/users",
fetcher,
{ suspense: true }
);
return { data, error };
};
出力表示するコンポーネント ./src/components/Pages/FetchCheck.tsx
import { FC, memo, Suspense, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { useAllUsersSWR } from "../../hooks/useAllUsersSWR";
const ResultComponent = () => {
const { data } = useAllUsersSWR();
return (
<>
<div>
<p>Fetch Users is below</p>
{data.map((user) => (
<div key={user.id}>{user.name}</div>
))}
</div>
</>
);
};
export const FetchCheck: FC = memo(() => {
const navigate = useNavigate();
const onClickHome = useCallback(() => {
navigate("/");
}, [navigate]);
return (
<>
<div>
<Suspense fallback={<p>厄介な広告ページの表示</p>}>
<ResultComponent />
</Suspense>
<button onClick={onClickHome}>to home</button>
</div>
</>
);
});
APIレスポンスの型指定 ./src/types/Users.ts
export type Users = {
id: number;
name: string;
username: string;
email: string;
address: {
street: string;
suite: string;
city: string;
zipcode: string;
geo: {
lat: string;
lng: string;
};
};
phone: string;
website: string;
company: {
name: string;
catchPhrase: string;
bs: string;
};
};
Repository
Discussion