© TOOLS BOX — Next.js / React / TypeScript コードサンプル集

サンプルガイド
←サンプル一覧
nextjsapi

TanStack Query でデータフェッチとローディング状態を管理する

TanStack Query を使ったデータフェッチ・ローディング・エラー状態管理の実装例。useQuery でシンプルに非同期状態を扱う。

難易度: 中級·更新: 2026-04-16·
tanstack-query

対応バージョン

nextjs 15react 19tanstack-query 5

前提環境

React の useState / useEffect の基本を理解していること

概要

@tanstack/react-query の useQuery を使うと、データフェッチのローディング・エラー・成功状態を宣言的に管理できる。 useState + useEffect による手動管理を置き換え、キャッシュ・リフェッチも自動で扱える。

インストール

npm install @tanstack/react-query

セットアップ(QueryClientProvider)

App Router では QueryClientProvider をクライアントコンポーネントとして用意する。

// src/components/providers/QueryProvider.tsx
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState } from "react";

export function QueryProvider({ children }: { children: React.ReactNode }) {
  const [client] = useState(() => new QueryClient());
  return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
}
// src/app/layout.tsx
import { QueryProvider } from "@/components/providers/QueryProvider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ja">
      <body>
        <QueryProvider>{children}</QueryProvider>
      </body>
    </html>
  );
}

useQuery でデータフェッチ

// src/components/UserList.tsx
"use client";

import { useQuery } from "@tanstack/react-query";

type User = {
  id: number;
  name: string;
  email: string;
};

async function fetchUsers(): Promise<User[]> {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  if (!res.ok) throw new Error("データの取得に失敗しました");
  return res.json();
}

export function UserList() {
  const { data, isLoading, isError, error } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
  });

  if (isLoading) return <p>読み込み中...</p>;
  if (isError) return <p>エラー: {error.message}</p>;

  return (
    <ul className="space-y-2">
      {data?.map((user) => (
        <li key={user.id} className="rounded border px-4 py-2 text-sm">
          <span className="font-medium">{user.name}</span>
          <span className="ml-2 text-gray-500">{user.email}</span>
        </li>
      ))}
    </ul>
  );
}

ポイント

  • queryKey はキャッシュのキーとして機能する。同じ queryKey のデータはキャッシュから返される
  • isLoading / isError / data で状態を分岐でき、useState による管理が不要になる
  • QueryClient を useState で初期化することで、リクエストをまたいだインスタンス共有を防ぐ
  • QueryProvider は "use client" が必要。Server Component のツリーに直接置けない

注意点

Next.js App Router では QueryClientProvider をクライアントコンポーネントとして設定する必要がある

関連サンプル

同じテーマや技術スタックを使った実装例

  • Redux Toolkit の RTK Query で API データフェッチとキャッシュを管理する

    RTK Query の createApi でエンドポイントを定義し、useGetQuery / useMutation フックでデータフェッチ・キャッシュ・自動再フェッチを管理する例。

  • Redux Toolkit の createAsyncThunk で非同期処理を管理する

    createAsyncThunk で API フェッチを定義し、pending / fulfilled / rejected の状態を extraReducers で管理する実装例。

  • TanStack Query の useMutation で POST / DELETE を管理する

    useMutation を使い、フォーム送信・削除などの副作用操作を型安全に管理する実装例。成功・エラー・ローディング状態を宣言的に扱う。

  • TanStack Query でクライアントサイドページネーションを実装する

    useQuery の page パラメータと keepPreviousData を使い、クライアントサイドでスムーズなページネーションを実装する例。

  • TanStack Query で Server Component からデータをプリフェッチする

    Server Component で prefetchQuery を実行し HydrationBoundary でクライアントに渡すことで、ウォーターフォールなしに TanStack Query のキャッシュをハイドレートする例。

関連仕様

このサンプルを理解するのに役立つ仕様や概念

  • FrameworkNext.jsReact ベースのフルスタックフレームワーク。SSR・SSG・App Router・API Routes を提供する。
←サンプル一覧に戻る