プログラミング フレームワーク ソフトウェア 公開日 2026.05.15 更新日 2026.05.15

TanStack Query(旧 React Query)とは何か?非同期データ取得とキャッシュの標準ライブラリ

TanStack Query(旧 React Query)は、`サーバから取ったデータをキャッシュし、適切に同期する』 ためのライブラリで、React / Solid / Vue / Svelte で使えます。`useState + useEffect + fetch』 で苦労していた多くの場面を `useQuery』 1行で置き換えられる、現代フロントエンドのデファクトです。

先に要点

  • TanStack Query(旧 React Query)は、`サーバから取ったデータ(server state)』 を扱う専用ライブラリ。`useState + useEffect + fetch + ローディング + エラー + 再取得』 を毎回書く苦痛を ` useQuery』 1行 で解消する。
  • 核は ` stale-while-revalidate』 のキャッシュ戦略。`古いキャッシュをまず表示 → バックグラウンドで新しいデータを取り直す → 変わっていれば更新』 という挙動を、デフォルトで提供する。
  • 提供機能は広い: ` キャッシュ管理 / 再試行 / 自動再取得(focus / online)/ ページネーション / 無限スクロール / 楽観的更新 / プリフェッチ / DevTools』。`データ取得まわりの定番ハマりどころ』 が一通り入っている。
  • React 専用ではない。` Solid / Vue / Svelte / Angular』 でも同じ概念で使えるtRPCHono RPC の標準クライアントとしても採用されている。

React Query ってよく聞くけど、Redux とどう違うの? useEffect で fetch するのと何が違うの?』 今は TanStack Query って名前変わった?』 ── 2018年頃から急速に広まった React Query は、2022年に TanStack Query へ改名し、現在はマルチフレームワーク対応の `サーバ状態ライブラリ』 として定着しました。

ざっくり言うと、TanStack Query は サーバから取ったデータをキャッシュして、必要なときに同期する』</strong> 専門ライブラリです。サーバ状態(server state)』 を扱うことに特化していて、`クライアント側だけの状態(UI 状態など)』 とは別物として扱う、というのが設計思想の核心です。

この記事では、2026年5月時点の TanStack Query v5 系をベースに、仕組み・基本の書き方・Redux 等との違い・採用判断軸 を整理します。 仕様は活発に変化しているので、最終確認は 公式ドキュメント を見るのが安全です。

なぜ TanStack Query が必要になったか

なぜわざわざ専用ライブラリが必要なのか』 を useState + useEffect』 と比較すると分かりやすくなります。

// `素朴な』 書き方
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    fetch(`/api/users/${userId}`)
      .then(r => r.json())
      .then(setUser)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [userId]);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error</p>;
  return <p>{user.name}</p>;
}

これに対して、TanStack Query では:

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

function UserProfile({ userId }) {
  const { data: user, isLoading, error } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
  });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error</p>;
  return <p>{user.name}</p>;
}

行数の差以上の違い

素朴な書き方では ` 別画面に行って戻ると毎回再取得』 `タブを切り替えるたびに再フェッチ』 `エラーで自動再試行する』 などが手動 / 未対応』。TanStack Query はこれらをデフォルトで適切に処理する。

キャッシュの共有

` 同じ `queryKey』 を別コンポーネントで使うと、自動で同じキャッシュを参照する』 → 同じデータが2回フェッチされる無駄が消える。

再取得のタイミング

` ウィンドウフォーカス時』 `ネットワーク再接続時』 `mount 時』 など、`いつ取り直すか』 を細かく設定できる。`画面を放置していたら古いデータが表示されたまま』 が起きづらい。

エラー / リトライ

` 失敗したら指数バックオフで自動リトライ』 が標準。`ネットワークの一瞬の不調』 で諦めない。

`非同期の細かい挙動を毎回手書きしなくていい』 のが、TanStack Query の最大の利点です。

キャッシュの考え方 — stale と fresh

TanStack Query のキャッシュは、` stale-while-revalidate』 という考え方に基づいています。

`fresh』 状態

取ったデータが `まだ新しい』 とみなされる期間。`staleTime』 で指定。デフォルトは 0 ms(取った瞬間に古くなる扱い)。

`stale』 状態

` まだキャッシュには残っているが、新しい値を取りに行ってもいい』 状態。表示は即時、裏側でリフェッチ。

`cacheTime』 / `gcTime』

` どのコンポーネントからも使われなくなった後、何分間キャッシュを保持するか』。デフォルトは 5分

refetch のトリガ

`stale なときに mount / window focus / network reconnect』 で自動再取得。`そんなに頻繁にいらない』 場合は `staleTime』 を伸ばす。

データを 絶対今の値』 か だいたい近い値』 のどちらで扱うか』 を staleTime』 でチームごとに調整するのが、TanStack Query の運用の中心です。

主要機能の一覧

`データ取得まわりの定番タスク』 が一通りそろっています。

機能 API 用途
取得 `useQuery』 GET 系。データを読む。
更新 `useMutation』 POST / PUT / DELETE 系。書き込み。
無効化 `queryClient.invalidateQueries』 ` この queryKey のキャッシュを古い扱いにする』。
楽観的更新 `onMutate / setQueryData / onError』 サーバ応答前に UI を仮更新。
無限スクロール `useInfiniteQuery』 ページネーション + `次へ』 を自動管理。
プリフェッチ `queryClient.prefetchQuery』 ` 次の画面に行く前に先取り』。
サスペンス連携 `useSuspenseQuery』 React Suspense と組み合わせる。
DevTools `@tanstack/react-query-devtools』 キャッシュ状態を視覚化。

`データ取得で手で書きたくない処理は、まず TanStack Query にあるか確認する』 だけで、ほぼ何でも見つかる印象です。

Redux / Zustand / Context との違い

`なんで状態管理ライブラリの代わりに使うの?』 という疑問は、よく出ます。

Redux / Zustand / Context TanStack Query
得意領域 クライアント状態(UI 状態、フォーム、モーダル) サーバ状態(API から取ったデータ)
キャッシュ 自前で実装 標準で提供
非同期 middleware や thunk で手書き 標準で提供
再取得 / 同期 手書き 標準で提供
主な責務 ` クライアントが持つべき状態』 ` サーバが真実とする状態のキャッシュ』
組み合わせ TanStack Query と併用がベスト Redux / Zustand と併用がベスト

要点は Redux 系と TanStack Query は競合ではなく、役割分担で併用する』</strong> ことです。サーバから取ったデータは TanStack Query、UI 状態(ダークモード / モーダル開閉)は Zustand / Context』 という棲み分けが2026 年現在の主流です。

楽観的更新の書き方

UX を高める典型機能 `楽観的更新』 の書き方を見ます。

const queryClient = useQueryClient();

const toggleLike = useMutation({
  mutationFn: (postId) =>
    fetch(`/api/posts/${postId}/like`, { method: 'POST' }),

  onMutate: async (postId) => {
    // 進行中の取得をキャンセル
    await queryClient.cancelQueries({ queryKey: ['posts'] });

    // 前の値を保持(ロールバック用)
    const previous = queryClient.getQueryData(['posts']);

    // 楽観的に更新
    queryClient.setQueryData(['posts'], (old) =>
      old.map(p => p.id === postId ? { ...p, liked: !p.liked } : p)
    );

    return { previous };
  },

  onError: (err, postId, context) => {
    // 失敗したら前の値に戻す
    queryClient.setQueryData(['posts'], context.previous);
  },

  onSettled: () => {
    queryClient.invalidateQueries({ queryKey: ['posts'] });
  },
});

楽観的更新とは

` サーバ応答を待たずに、UI を先に更新する』 こと。ボタンを押したら即色が変わる、いいねが即反映する、といった `早く感じる UX』 を実現する。

ロールバック

失敗時に `前の値に戻す』 ロジックが必須。TanStack Query の `onMutate → onError』 パターンで自然に書ける。

最終的な同期

`onSettled』 で ` 関連キャッシュを invalidate』 して、最終的にはサーバの値で上書きされるようにする。

React 19 との関係

React 19 の `useOptimistic』 は Server Actions と組み合わせて使う仕組み。`TanStack Query で全部完結する』 ケースと `React 標準の useOptimistic を使う』 ケースが棲み分かれつつある。

非同期処理の 応答までの空白』 をなくす』 のが楽観的更新の核心で、TanStack Query はこれを正攻法で書きやすくしてくれます。

いつ TanStack Query を使うか

採用判断の目安を整理します。

向いている

React / Solid / Vue / Svelte の中〜大規模アプリ、② 複数画面で同じデータを表示する SPA、③ 非同期取得が多い管理画面 / SaaS、④ tRPC / GraphQL Code Generator の組み合わせ。

慎重に

① 純粋に App Router + RSC + Server Actions だけで完結する小規模アプリ(`useQuery が要らない』 ケースが増える)、② `1ページだけ』 のような極小プロジェクト、③ サーバ側で全部レンダリング前提のサイト。

RSC / Server Actions との関係

` データ取得の主役を RSC に寄せる』 場合、TanStack Query の必要性は下がる。ただし、`クライアント側のリアルタイム更新』 `フォーカス時の再取得』 が必要な場面では、依然として有力。

tRPC との相性

tRPC の React 統合は ` TanStack Query をベースに作られている』。`tRPC を使う = TanStack Query もセットで使う』 と言って差し支えない。

React 系のフルスタックアプリ』 を作るなら、いまも 必須スキル』 に近い位置にいます。

ハマりやすいポイント

便利な反面、現場で踏みやすい注意点も整理します。

①`queryKey』 設計

` queryKey が同じだとキャッシュを共有する』 ので、`配列の構造』 を最初に決めておく。` ['posts', { userId, page }]』 のような構造 がチーム標準的。

② staleTime デフォルト 0

` 取った瞬間 stale 扱い』 になり、毎回 refetch がトリガーされやすい。`staleTime: 1000 * 60』 などを `defaultOptions』 で設定すると、無駄な再取得が減る。

③ 無効化漏れ

` 更新したのにリストが古いまま』 が起きやすい。`useMutation の onSuccess で invalidateQueries』 を必ず入れる。

④ DevTools を入れていない

` どのキャッシュが今 stale で、どれが fresh か』 を視覚化できる DevTools が必須レベルに便利。開発時は必ず入れる。

`設定の妥当性を体感で詰める』 のが、TanStack Query の運用を綺麗にする最大のコツです。

AI 時代の TanStack Query

AI 連携の文脈でも TanStack Query は活躍します。

AI 応答のストリーミング

` useQuery で AI レスポンスを取りつつ、ストリーミングは別途処理』 のような構成が組める。`生成中の状態 + 過去履歴の表示』 を統一的に扱える。

プリフェッチで体感速度向上

` 次に必要そうな AI 応答』 をプリフェッチしておくことで、`クリック後の待ち時間』 を実質ゼロにできる。AI のレスポンス遅さを UX 上隠せる。

楽観的更新 × AI

` AI チャットで送信 → 即ユーザーメッセージを表示 → AI 応答が返ったら追加』 という典型的な UX を、`useMutation + 楽観的更新』 で素直に書ける。

tRPC + TanStack Query + AI

` AI 呼び出しを tRPC mutation として定義 → TanStack Query 統合で再取得 / 楽観的更新』 という構成は、AI 機能を持つアプリの定番パターン。

AI 応答の不確実な遅延』 を TanStack Query のキャッシュとプリフェッチ』 で吸収する、というのは AI 時代の UX 設計で頻出するパターンです。

TanStack Query に関するよくある質問

Q. React Query と TanStack Query は同じものですか?

A. 同じです』</strong>。2022 年にReact Query』 から TanStack Query』 に改名し、React 以外のフレームワーク(Solid / Vue / Svelte / Angular)もサポートする多目的ライブラリになりました。React Query』 は React 向けアダプタの呼称として残っています。

Q. SWR と TanStack Query、どちらを選ぶべきですか?

A. 用途と好みで分けます。 SWR は Vercel 製の軽量・シンプル路線』</strong>、<strong> TanStack Query は機能が豊富で 何でもできる』 路線』</strong>。小さなアプリで軽さ重視』 なら SWR、`本格的な機能と DevTools が欲しい』 なら TanStack Query、というのがざっくりの選び方です。

Q. RSC と Server Actions だけで完結する場合、TanStack Query は不要ですか?

A. ケースバイケース』</strong>です。完全に読みは RSC、書きは Server Actions、再取得は revalidatePath』 で済む場合は不要です。ただし、Realtime な再取得』 フォーカス再取得』 `楽観的更新』 が必要な場面では、TanStack Query を併用する設計が依然として有効です。

Q. tRPC と TanStack Query は必ずセットですか?

A. React で tRPC を使う場合は事実上セット』</strong>です。tRPC の React Hooks』 は内部的に TanStack Query を使っており、useQuery / useMutation』 と同じ感覚で trpc.x.useQuery()』 が使えます。

Q. キャッシュ無効化を全部書くのが面倒です。

A. queryKey の階層を意識して、まとめて invalidate する』</strong>のが定石です。queryClient.invalidateQueries({ queryKey: ['posts'] })』 だけで `['posts', ...]』 系すべてのクエリを無効化できます。

Q. SSR ではどう使いますか?

A. サーバ側でデータをフェッチ → dehydrate してクライアントに渡す → hydrate』</strong>のパターンが基本です。Next.js / Remix での専用ヘルパー(HydrationBoundary』 等)があります。

Q. TanStack Query を学ぶ最短ルートは?

A. ① useQuery』 で1つ取得、② useMutation』 で1つ更新、③ queryClient.invalidateQueries』 で再取得、④ DevTools をインストールして挙動を観察、の4段階が王道です。動かしながらキャッシュ状態を見る』 のが、TanStack Query の理解を加速する最大のコツです。

参考リンク

あとで見返すならここで保存

読み終わったあとに残しておきたい記事は、お気に入りからまとめて辿れます。