Claude CodeでTanStack Queryを使いこなすデータ取得戦略
TanStack Query(React Query)をClaude Codeで効率的に実装する方法を解説。キャッシュ戦略、楽観的更新、無限スクロールなど実践パターンを紹介します。
TanStack Queryでサーバー状態管理を最適化する
TanStack Query(旧React Query)はサーバー状態の取得・キャッシュ・同期を宣言的に管理するライブラリです。Claude Codeを使えば、複雑なキャッシュ戦略や楽観的更新も素早く実装できます。
基本的なクエリ設計
Claude Codeにデータ取得パターンを依頼しましょう。
> TanStack Queryでユーザー一覧のクエリを作成して。
> ページネーション、検索フィルタ、自動リフレッシュ対応で。
import { useQuery, keepPreviousData } from "@tanstack/react-query";
// クエリキーファクトリー
export const userKeys = {
all: ["users"] as const,
lists: () => [...userKeys.all, "list"] as const,
list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
details: () => [...userKeys.all, "detail"] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
};
interface UserFilters {
page: number;
perPage: number;
search?: string;
role?: string;
}
export function useUsers(filters: UserFilters) {
return useQuery({
queryKey: userKeys.list(filters),
queryFn: () => fetchUsers(filters),
placeholderData: keepPreviousData,
staleTime: 5 * 60 * 1000, // 5分間はキャッシュを使用
refetchOnWindowFocus: true,
});
}
export function useUser(id: string) {
return useQuery({
queryKey: userKeys.detail(id),
queryFn: () => fetchUser(id),
enabled: !!id,
staleTime: 10 * 60 * 1000,
});
}
楽観的更新の実装
ミューテーションと楽観的更新のパターンをClaude Codeに生成してもらいます。
import { useMutation, useQueryClient } from "@tanstack/react-query";
export function useUpdateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: { id: string; updates: Partial<User> }) =>
updateUser(data.id, data.updates),
onMutate: async ({ id, updates }) => {
// 進行中のクエリをキャンセル
await queryClient.cancelQueries({ queryKey: userKeys.detail(id) });
// 現在のデータをバックアップ
const previousUser = queryClient.getQueryData(userKeys.detail(id));
// キャッシュを楽観的に更新
queryClient.setQueryData(userKeys.detail(id), (old: User) => ({
...old,
...updates,
}));
return { previousUser };
},
onError: (_err, { id }, context) => {
// エラー時にロールバック
if (context?.previousUser) {
queryClient.setQueryData(userKeys.detail(id), context.previousUser);
}
},
onSettled: (_data, _error, { id }) => {
// 成功・失敗に関わらず再取得
queryClient.invalidateQueries({ queryKey: userKeys.detail(id) });
queryClient.invalidateQueries({ queryKey: userKeys.lists() });
},
});
}
無限スクロールの実装
useInfiniteQueryを使った無限スクロールもClaude Codeで素早く実装できます。
import { useInfiniteQuery } from "@tanstack/react-query";
export function useInfiniteUsers(search?: string) {
return useInfiniteQuery({
queryKey: ["users", "infinite", { search }],
queryFn: ({ pageParam }) =>
fetchUsers({ page: pageParam, perPage: 20, search }),
initialPageParam: 1,
getNextPageParam: (lastPage) =>
lastPage.hasNext ? lastPage.page + 1 : undefined,
getPreviousPageParam: (firstPage) =>
firstPage.hasPrev ? firstPage.page - 1 : undefined,
});
}
function UserInfiniteList() {
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
useInfiniteUsers();
const users = data?.pages.flatMap((page) => page.users) ?? [];
return (
<div>
{users.map((user) => (
<UserCard key={user.id} user={user} />
))}
{hasNextPage && (
<button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
{isFetchingNextPage ? "読み込み中..." : "もっと見る"}
</button>
)}
</div>
);
}
プリフェッチとSSR対応
Next.jsなどでのサーバーサイドプリフェッチも実装できます。
import { QueryClient, dehydrate, HydrationBoundary } from "@tanstack/react-query";
export async function getServerSideProps() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery({
queryKey: userKeys.list({ page: 1, perPage: 20 }),
queryFn: () => fetchUsers({ page: 1, perPage: 20 }),
});
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}
export default function UsersPage({
dehydratedState,
}: {
dehydratedState: unknown;
}) {
return (
<HydrationBoundary state={dehydratedState}>
<UserList />
</HydrationBoundary>
);
}
カスタムクエリフックのパターン
実務では再利用可能なカスタムフックとして設計します。
function useOptimisticDelete<T extends { id: string }>(
queryKey: readonly unknown[],
deleteFn: (id: string) => Promise<void>
) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: deleteFn,
onMutate: async (id) => {
await queryClient.cancelQueries({ queryKey });
const previous = queryClient.getQueryData(queryKey);
queryClient.setQueryData(queryKey, (old: T[] | undefined) =>
old?.filter((item) => item.id !== id)
);
return { previous };
},
onError: (_err, _id, context) => {
queryClient.setQueryData(queryKey, context?.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey });
},
});
}
まとめ
TanStack Queryはサーバー状態管理の複雑さを大幅に軽減してくれます。Claude Codeを活用すれば、クエリキー設計、楽観的更新、無限スクロールなどの複雑なパターンも短時間で実装可能です。
状態管理の全体設計はZustand状態管理ガイドを、APIの型安全性はtRPC型安全API開発を参照してください。TanStack Query公式ドキュメントも確認しておきましょう。
関連記事
Claude CodeでCORS設定完全ガイド:クロスオリジン通信の実践解説
Claude Codeを活用したCORS設定の完全ガイド。プリフライトリクエスト、認証付きリクエスト、トラブルシューティングまで実践的に解説します。
Claude Codeで通貨フォーマットを正しく実装する
Claude Codeを使って、多通貨対応・ロケール別フォーマット・為替レート変換など、通貨の表示と処理を正しく実装する方法を解説します。
Claude CodeでDiscord Botを開発する実践ガイド
Claude Codeを活用したDiscord Botの開発方法を解説。discord.js、スラッシュコマンド、ボタン操作、Embed、音声チャンネル連携まで実践的に紹介します。