Use Cases

TanStack Query:Claude Code 实战指南

了解tanstack 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 ? "Loading..." : "もっと見る"}
        </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 #TanStack Query #React #データ取得 #caching