Cursor TanStack 编码规范:来自 PatrickJS/awesome-cursorrules (40k stars) 的 tan,适用于各类文档与内容的智能化处理。
Cursor TanStack 编码规范:来自 PatrickJS/awesome-cursorrules (40k stars) 的 tan,适用于各类文档与内容的智能化处理。
**文件来源:** PatrickJS/awesome-cursorrules → `rules/tanstack-query.mdc`
**原仓库:** https://github.com/PatrickJS/awesome-cursorrules
**评分:** ⭐ 仓库 40k stars (社区最权威 Cursor rules 合集)
把 `tanstack-query.mdc` 这条 Cursor 编码规则打包成可调用的 AI skill,帮你把代码生成统一到一致的标准上。
> TanStack Query v5 (React Query) patterns including queryOptions helper, query key factories, mutations, optimistic updates, infinite queries, Suspense mode, and prefetching
globs: ["src/**/*.tsx", "src/**/*.ts", "src/queries/**/*"]
alwaysApply: false
---
You are an expert in TanStack Query v5 (React Query), TypeScript, and async state management.
## Core Principles
- TanStack Query manages server state — NOT a general client state manager
- Every query needs a stable, serializable query key that uniquely describes the data
- Mutations handle writes; queries handle reads — never blur this boundary
- Use `queryOptions()` helper (v5) for reusable, co-located query definitions
- v5 breaking change: `useQuery` only accepts options object form — no positional args
## QueryClient Setup
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60,
retry: (count, error: any) => error?.status !== 404 && count < 2,
},
},
})
## Query Key Factory Pattern
export const postKeys = {
all: ['posts'] as const,
lists: () => [...postKeys.all, 'list'] as const,
list: (filters?: PostFilters) => [...postKeys.lists(), filters] as const,
details: () => [...postKeys.all, 'detail'] as const,
detail: (id: string) => [...postKeys.details(), id] as const,
}
## queryOptions Helper (v5)
export const postQueryOptions = (id: string) =>
queryOptions({
queryKey: postKeys.detail(id),
queryFn: () => fetchPost(id),
staleTime: 1000 * 60 * 5,
})
// In component
const { data } = useQuery(postQueryOptions(postId))
// In router loader
loader: ({ params, context: { queryClient } }) =>
queryClient.ensureQueryData(postQueryOptions(params.postId))
## Mutations
const { mutate, isPending } = useMutation({
mutationFn: (input: CreatePostInput) => createPost(input),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: postKeys.lists() })
},
onError: (error) => toast.error(error.message),
})
## Optimistic Updates
const mutation = useMutation({
mutationFn: updatePost,
onMutate: async (updated) => {
await queryClient.cancelQueries({ queryKey: postKeys.detail(updated.id) })
const previous = queryClient.getQueryData(postKeys.detail(updated.id))
queryClient.setQueryData(postKeys.detail(updated.id), updated)
return { previous }
},
onError: (_, updated, ctx) => {
queryClient.setQueryData(postKeys.detail(updated.id), ctx?.previous)
},
onSettled: (_, __, updated) => {
queryClient.invalidateQueries({ queryKey: postKeys.detail(updated.id) })
},
})
## Infinite Queries
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: postKeys.lists(),
queryFn: ({ pageParam }) => fetchPosts({ cursor: pageParam }),
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage) => lastPage.nextCursor,
})
const allPosts = data?.pages.flatMap((p) => p.items) ?? []
## Suspense Mode (v5)
// useSuspenseQuery — no isLoading needed, Suspense handles it
const { data } = useSuspenseQuery(postQueryOptions(postId))
// Wrap with <Suspense fallback={<S
...(完整内容在原仓库)...
## 数据来源
- 仓库: PatrickJS/awesome-cursorrules (40,581 stars, 257 个 .mdc 规则)
- 抓取时间: 2026-08-17
- License: 跟随原仓库(MIT)
## 联系方式
有问题或建议,在本 skill 下留言。
把 `tanstack-query.mdc` 这条 Cursor 编码规则打包成可调用的 AI skill,帮你把代码生成统一到一致的标准上。
> TanStack Query v5 (React Query) patterns including queryOptions helper, query key factories, mutations, optimistic updates, infinite queries, Suspense mode, and prefetching