はじめに
こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
前回の Tanstack Query に続き、本日は fetch の際に使用できる useQuery についてです。
API からデータを取るとき、ローディングやエラー処理を毎回書くのは大変です。そこで、今回紹介するuseQueryを使うと、キャッシュ・リフェッチ・エラー処理まで一括管理できます。
今回は useQuery の活用法や私のディレクトリ構成まで載せておこうと思います
インストール
まずはライブラリを導入します。
npm i @tanstack/react-query
npm i -D @tanstack/react-query-devtools
アプリ全体を囲む設定
React アプリ全体を QueryClientProvider でラップして、どこからでも Query を使えるようにします。
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import App from './App';
const queryClient = new QueryClient();
export default function Root() {
return (
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
📌 ReactQueryDevtools を入れておくと、キャッシュやフェッチ状態を GUI で確認できて便利。
useQuery の基本
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
const fetchStudents = async () => {
const { data } = await axios.get('/api/students');
return data;
};
export const Students = () => {
const { data, isPending, error } = useQuery({
queryKey: ['students'],
queryFn: fetchStudents,
});
if (isPending) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (
<ul>
{data.map((s: { id: number; name: string }) => (
<li key={s.id}>{s.name}</li>
))}
</ul>
);
};
-
isLoading: 初回フェッチ時だけ true -
isPending: フェッチ中は常に true
実務でのディレクトリ構成
現場では「機能ごとにまとめる」スタイルが多いです。
src/
features/
students/
api/studentApi.ts // API呼び出し
queries/useStudentsQuery.ts // useQueryフック
key.ts // queryKeyの定義
1. API 呼び出し(features/students/api/studentApi.ts)
import { api } from '@/lib/api';
export const fetchStudents = async () => {
const { data } = await api.get('/students');
return data;
};
2. queryKey の定義(features/students/key.ts)
export const studentKeys = {
all: ['students'] as const,
list: () => [...studentKeys.all, 'list'] as const,
detail: (id: number) => [...studentKeys.all, 'detail', id] as const,
};
3. useQuery フック(features/students/queries/useStudentsQuery.ts)
import { useQuery } from '@tanstack/react-query';
import { fetchStudents } from '../api/studentApi';
import { studentKeys } from '../key';
export const useStudentsQuery = () =>
useQuery({
queryKey: studentKeys.list(),
queryFn: fetchStudents,
});
4. コンポーネントで利用(components/Students.tsx)
import { useStudentsQuery } from '@/features/students/queries/useStudentsQuery';
export const Students = () => {
const { data, isPending, error } = useStudentsQuery();
if (isPending) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (
<ul>
{data?.map((s) => (
<li key={s.id}>{s.name}</li>
))}
</ul>
);
};
まとめ
-
useQueryはサーバーからデータを取るための基本フック。 - 状態フラグは
isPendingを使うのが最近の流れ。 - 実務では features/配下に api, queries, key.ts をまとめる構成 が多い。
- 最初に
QueryClientProviderでアプリ全体を囲むのを忘れずに!
参考記事
とても分かりやすく Tanstack Query の概要を知る際に利用させていただきました。
なんとなく Tanstack Query いいなって思ったらぜひ以下リンクから詳細を見てみてください。
特に key.ts の書き方やdata,error,isPending という返却値以外に指定する値なども書いてあるので細かい制御をする際にためになると思います。