К основному содержанию
правило

tanstack-query-v5-cursorrules-prompt-file — правило для Cursor

Правило для Cursor, которое задаёт агенту стиль работы с TanStack Query v5: ключи запросов, мутации, оптимистичные обновления, Suspense и префетчинг.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/tanstack-query-v5-cursorrules-prompt-file.mdc
Открыть на GitHub

Что делает tanstack-query-v5-cursorrules-prompt-file

Это файл правил для Cursor, который подключается к проекту и описывает, как писать код на TanStack Query v5. Внутри — набор соглашений: ключи запросов всегда массивами, фабрика ключей вместо строк, разделение чтения и записи между useQuery и useMutation, хелпер queryOptions() для переиспользуемых определений.

Правило разбирает и практические куски: настройку QueryClient в main.tsx, оптимистичные обновления через onMutate с откатом в onError, бесконечные запросы с getNextPageParam, префетчинг по наведению и в лоадерах роутера, инвалидацию кэша. Отдельно отмечено ломающее изменение v5: useQuery больше не принимает позиционные аргументы, только объект с опциями. Если в проекте ещё висят вызовы старого вида, правило будет тянуть их к новому синтаксису — это повод проверить код до подключения.

Есть разделы про Suspense с useSuspenseQuery, обработку ошибок через throwOnError и условный retry, а также заметки по TypeScript. Правило не применяется автоматически: в frontmatter стоит alwaysApply: false, а globs задан как **/*.

Какие задачи решает

  • привести ключи запросов к единому виду через фабрику
  • переписать вызовы useQuery под объектную форму v5
  • сделать оптимистичное обновление с откатом при ошибке
  • настроить бесконечную подгрузку списка по курсору
  • убрать спиннеры за счёт префетчинга в лоадере

Примеры запросов агенту

  • Создай фабрику ключей запросов для сущности post по правилам TanStack Query v5
  • Добавь мутацию создания поста с инвалидацией списка и тостом об успехе
  • Переведи этот компонент на useSuspenseQuery с Suspense и ErrorBoundary

Как установить tanstack-query-v5-cursorrules-prompt-file

Вручную: положить файлы

.cursor/rules/tanstack-query-v5-cursorrules-prompt-file.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о tanstack-query-v5-cursorrules-prompt-file

Как установить tanstack-query-v5-cursorrules-prompt-file в Cursor?

Создайте файл .cursor/rules/tanstack-query-v5-cursorrules-prompt-file.mdc в проекте и вставьте в него содержимое правила.

Что делает это правило?

Задаёт агенту Cursor соглашения по TanStack Query v5: структуру ключей, queryOptions(), мутации, оптимистичные обновления, бесконечные запросы, Suspense и префетчинг.

Правило применяется ко всем файлам сразу?

Нет. В frontmatter указано alwaysApply: false, поэтому правило нужно подключать осознанно, хотя globs покрывает **/*.

Исходный текст

tanstack-query-v5-cursorrules-prompt-file.mdc · CC0-1.0
---
description: "Cursor rules for TanStack Query v5 with query options, query key factories, mutations, optimistic updates, infinite queries, Suspense, and prefetching."
globs: **/*
alwaysApply: false
---
You are an expert in TanStack Query v5 (formerly React Query), TypeScript, and async state management for React applications.

# TanStack Query v5 Guidelines

## Core Philosophy
- TanStack Query manages server state — it is NOT a general state manager for client-only state
- Every query should have a stable, serializable query key that uniquely describes the data
- Mutations handle writes; queries handle reads — never blur this boundary
- Prefer `queryOptions()` helper for reusable, co-located query definitions
- v5 breaking changes: `useQuery` no longer accepts positional args; always use the options object form

## Setup
```tsx
// main.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60, // 1 minute default stale time
      retry: 2,
      refetchOnWindowFocus: true,
    },
  },
})

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <YourApp />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  )
}
```

## Query Keys
- Always structure keys as arrays: `['entity', 'list']`, `['entity', 'detail', id]`
- Use a query key factory to avoid typos and enable easy invalidation
```ts
// queryKeys.ts
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)
- Use `queryOptions()` to define queries once and reuse across components and loaders
```ts
import { queryOptions } from '@tanstack/react-query'

export const postQueryOptions = (id: string) =>
  queryOptions({
    queryKey: postKeys.detail(id),
    queryFn: () => fetchPost(id),
    staleTime: 1000 * 60 * 5, // 5 min
  })

// In component
const { data } = useQuery(postQueryOptions(postId))

// In router loader (TanStack Router integration)
loader: ({ params, context: { queryClient } }) =>
  queryClient.ensureQueryData(postQueryOptions(params.postId))
```

## useQuery
```tsx
const {
  data,
  isLoading,    // true only on first load with no cached data
  isFetching,   // true whenever a fetch is in-flight
  isError,
  error,
  isSuccess,
} = useQuery({
  queryKey: postKeys.detail(postId),
  queryFn: () => fetchPost(postId),
  enabled: !!postId, // disable query if params not ready
})
```

## useMutation
```tsx
const { mutate, mutateAsync, isPending } = useMutation({
  mutationFn: (newPost: CreatePostInput) => createPost(newPost),
  onSuccess: (data) => {
    // Invalidate and refetch
    queryClient.invalidateQueries({ queryKey: postKeys.lists() })
    toast.success('Post created!')
  },
  onError: (error) => {
    toast.error(error.message)
  },
})

// Usage
mutate({ title: 'Hello', body: '...' })
```

## Optimistic Updates
```tsx
const queryClient = useQueryClient()

const mutation = useMutation({
  mutationFn: updatePost,
  onMutate: async (updatedPost) => {
    await queryClient.cancelQueries({ queryKey: postKeys.detail(updatedPost.id) })
    const previous = queryClient.getQueryData(postKeys.detail(updatedPost.id))
    queryClient.setQueryData(postKeys.detail(updatedPost.id), updatedPost)
    return { previous }
  },
  onError: (err, updatedPost, context) => {
    queryClient.setQueryData(postKeys.detail(updatedPost.id), context?.previous)
  },
  onSettled: (_, __, updatedPost) => {
    queryClient.invalidateQueries({ queryKey: postKeys.detail(updatedPost.id) })
  },
})
```

## Infinite Queries
```tsx
const {
  data,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
} = useInfiniteQuery({
  queryKey: postKeys.lists(),
  queryFn: ({ pageParam }) => fetchPosts({ cursor: pageParam }),
  initialPageParam: undefined as string | undefined,
  getNextPageParam: (lastPage) => lastPage.nextCursor,
})

// data.pages is an array of page results — flatten for rendering
const allPosts = data?.pages.flatMap((page) => page.items) ?? []
```

## Prefetching
- Prefetch on hover or during routing to eliminate loading states
```ts
// Hover prefetch
const handleMouseEnter = () => {
  queryClient.prefetchQuery(postQueryOptions(postId))
}

// In router loader (eliminates all loading spinners)
export const Route = createFileRoute('/posts/$postId')({
  loader: ({ context: { queryClient }, params }) =>
    queryClient.ensureQueryData(postQueryOptions(params.postId)),
})
```

## Cache Invalidation Patterns
```ts
// Invalidate all post queries
queryClient.invalidateQueries({ queryKey: postKeys.all })

// Invalidate only post lists
queryClient.invalidateQueries({ queryKey: postKeys.lists() })

// Remove from cache entirely
queryClient.removeQueries({ queryKey: postKeys.detail(id) })

// Directly update cache without refetch
queryClient.setQueryData(postKeys.detail(id), newData)
```

## Suspense Mode
- Use `useSuspenseQuery` for Suspense-based data fetching (v5)
- Wrap with `<Suspense fallback={<Skeleton />}>`
- Pair with `<ErrorBoundary>` for error handling
```tsx
// No need to handle isLoading — Suspense handles it
const { data } = useSuspenseQuery(postQueryOptions(postId))
```

## Performance Best Practices
- Set appropriate `staleTime` per query — defaults to `0` (always stale)
- Use `select` to transform/subscribe to only relevant slices of data
- Use `placeholderData: keepPreviousData` for pagination to avoid layout shifts
- Avoid creating `QueryClient` inside components — instantiate once at app root
- Use `notifyOnChangeProps` to limit re-renders to only relevant data changes

## Error Handling
- Use `throwOnError: true` to bubble errors to the nearest ErrorBoundary
- Use `retry` function for conditional retry logic (e.g., skip retry on 404)
```ts
retry: (failureCount, error) => {
  if (error.status === 404) return false
  return failureCount < 3
},
```

## TypeScript Tips
- Always type `queryFn` return value explicitly or infer from typed API functions
- Use `QueryObserverResult<TData, TError>` to type hook return values
- Use `UseMutationResult<TData, TError, TVariables>` for mutations

© PatrickJS · CC0-1.0 · PatrickJS/awesome-cursorrules

Похожие правила IDE

Все правила IDE по теме «Фронтенд и UI» →
tanstack-query tanstack-skills Скилл подсказывает агенту, как работать с TanStack Query v5: кэширование, инвалидация, мутации и оптимистичные обновления. CX Codex +1 9 900установок tanstack-query-best-practices DeckardGer Свод правил TanStack Query для React: ключи запросов, кеш, мутации, SSR. Подключается к Claude Code, Codex, Cursor и Copilot — чтобы загрузка данных в проекте шла по одной схеме. CX Codex +1 12 800установок react-query Mindrally Задаёт агенту правила работы с React Query: кэширование, фоновые обновления, инвалидация запросов и оптимистичные апдейты. CX Codex +1 1 400установок router-query TanStack Связывает TanStack Router с TanStack Query для предзагрузки данных в лоадерах, кэширования через useSuspenseQuery и изоляции QueryClient при SSR. CX Codex +1 366установок react-vite-dashboard официальный google-labs-code Скилл превращает макеты из Stitch в рабочий код дашборда на React и Vite. Он связывает дизайн-токены из DESIGN.md с кодом и подключает выборку данных через TanStack Query. CX Codex +1 5 500установок clerk-tanstack-patterns clerk Подсказывает агенту, как подключить Clerk к TanStack React Start: защита маршрутов, createServerFn, лоадеры и middleware. CX Codex +1 15 500установок

Из того же набора68

typescript-nextjs-supabase-cursorrules-prompt-file Правило для Cursor, которое держит TypeScript-код на Next.js App Router и Supabase в одном стиле: серверные компоненты, Shadcn UI, Tailwind. ★ 41 011звёзд репо typescript-code-convention-cursorrules-prompt-file Правило задаёт Cursor стиль кода на TypeScript в проектах на Next.js App Router, React, Expo, tRPC и Tailwind. Пригодится, когда агент пишет код вразнобой. ★ 41 011звёзд репо tauri-svelte-typescript-guide-cursorrules-prompt-f Правило для Cursor, которое задаёт агенту стиль работы с десктопными приложениями на Tauri: Svelte во фронтенде, TypeScript для типов. ★ 41 011звёзд репо tanstack-router Правило для Cursor, которое задаёт агенту стандарты TanStack Router v1: файловые маршруты, типизация параметров и загрузка данных через loader. ★ 41 011звёзд репо tailwind-react-firebase-cursorrules-prompt-file Правило для Cursor задаёт, как писать мобильное веб-приложение на Tailwind, React и Firebase: сначала мобильная вёрстка, потом остальное. ★ 41 011звёзд репо sveltekit-typescript-guide-cursorrules-prompt-file Правило для Cursor, которое настраивает агента на Svelte 5, SvelteKit и TypeScript: структура проекта, руны, состояние. ★ 41 011звёзд репо svelte Правило для Cursor с набором практик по Svelte: структура компонентов, реактивность, сторы, роутинг через SvelteKit и тесты. Пригодится, когда агент пишет или правит код на Svelte. ★ 41 011звёзд репо solidjs-tailwind-cursorrules-prompt-file Правило для Cursor, которое задаёт агенту стиль кода на Solid.js с Tailwind CSS: сигналы, утилитарные классы, структура папок. ★ 41 011звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой