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

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

Правило задаёт паттерны для Next.js App Router и TanStack Query v5: гидратация кэша, Server Actions и оптимистичные обновления.

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

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

Правило направляет Cursor при работе с Next.js App Router, TypeScript и TanStack Query v5. Оно разделяет зоны ответственности: Server Components получают начальные данные, а Client Components используют TanStack Query для интерактивных запросов, мутаций, polling и оптимистичных обновлений.

Внутри описаны QueryClientProvider, HydrationBoundary, предварительная загрузка и согласованные ключи запросов. Server Actions предлагаются как mutationFn, а route handlers в src/app/api/ служат API-слоем для fetch-функций. Также разобраны откат оптимистичных изменений и бесконечные запросы.

Правило охватывает **/*, но alwaysApply: false означает, что Cursor не применяет его постоянно. Для проекта нужны Next.js App Router и TanStack Query v5.

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

  • настроить гидратацию кэша между Server и Client Components
  • связать Server Actions с мутациями TanStack Query
  • добавить откат оптимистичного обновления
  • разделить запросы между Server Components и Client Components
  • организовать infinite scroll через route handlers

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

  • Настрой страницу постов в Next.js App Router через HydrationBoundary и предварительную загрузку TanStack Query.
  • Свяжи Server Action создания поста с мутацией и инвалидируй список после успеха.
  • Добавь оптимистичное обновление поста с откатом при ошибке по правилам проекта.

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

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

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

Во frontmatter: description, globs, alwaysApply

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

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

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

Поместите файл правила по пути .cursor/rules/nextjs-tanstack-query-cursorrules-prompt-file.mdc.

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

Правило подсказывает Cursor, как сочетать Server Components, Client Components и TanStack Query v5 в Next.js App Router. Оно охватывает гидратацию, Server Actions, мутации и оптимистичные обновления.

Почему в правиле используется HydrationBoundary?

Данные предварительно загружаются в Server Component, затем состояние Query cache передаётся в Client Component через HydrationBoundary. Это убирает загрузку данных на первом клиентском рендере.

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

nextjs-tanstack-query-cursorrules-prompt-file.mdc · CC0-1.0
---
description: "Cursor rules for Next.js App Router with TanStack Query v5, covering the HydrationBoundary pattern, Server Actions as mutations, and optimistic updates."
globs: **/*
alwaysApply: false
---
You are an expert in Next.js (App Router), TanStack Query v5, TypeScript, and combining server components with client-side data fetching.

# Next.js App Router + TanStack Query v5 Guidelines

## Architecture Philosophy
- Server Components fetch data directly (no TanStack Query needed there)
- TanStack Query lives in Client Components for interactive, real-time, or user-triggered data
- Use React Server Components for initial page data; TanStack Query for mutations, polling, and optimistic updates
- Hydrate the Query cache from server to avoid client waterfalls on first load

## Provider Setup with Hydration
```tsx
// src/providers/query-provider.tsx
'use client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { useState } from 'react'

export function QueryProvider({ children }: { children: React.ReactNode }) {
  const [queryClient] = useState(
    () =>
      new QueryClient({
        defaultOptions: {
          queries: {
            staleTime: 60 * 1000,
            retry: (count, error: any) => error?.status !== 404 && count < 2,
          },
        },
      }),
  )

  return (
    <QueryClientProvider client={queryClient}>
      {children}
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  )
}

// src/app/layout.tsx
import { QueryProvider } from '@/providers/query-provider'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <QueryProvider>{children}</QueryProvider>
      </body>
    </html>
  )
}
```

## Hydration Pattern (Server → Client Cache)
- Prefetch in Server Components, dehydrate state, rehydrate in client
- This eliminates client-side loading states on first render
```tsx
// src/app/posts/page.tsx (Server Component)
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'
import { postsQueryOptions } from '@/queries/posts'
import { PostsList } from './_components/posts-list'

export default async function PostsPage() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery(postsQueryOptions())

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <PostsList />
    </HydrationBoundary>
  )
}

// src/app/posts/_components/posts-list.tsx
'use client'
import { useQuery } from '@tanstack/react-query'
import { postsQueryOptions } from '@/queries/posts'

export function PostsList() {
  // Reads from pre-populated cache — no loading spinner
  const { data: posts } = useQuery(postsQueryOptions())
  return <ul>{posts?.map(p => <li key={p.id}>{p.title}</li>)}</ul>
}
```

## Query Definitions
```ts
// src/queries/posts.ts
import { queryOptions } from '@tanstack/react-query'

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,
}

export const postsQueryOptions = (filters?: PostFilters) =>
  queryOptions({
    queryKey: postKeys.list(filters),
    queryFn: () => fetch(`/api/posts`).then(r => r.json()),
  })

export const postDetailQueryOptions = (id: string) =>
  queryOptions({
    queryKey: postKeys.detail(id),
    queryFn: () => fetch(`/api/posts/${id}`).then(r => r.json()),
    staleTime: 1000 * 60 * 5,
  })
```

## Server Actions + Mutations
- Use Next.js Server Actions as the `mutationFn` in TanStack Query mutations
- This gives you type-safe server mutations WITH optimistic update/rollback capabilities
```tsx
// src/app/posts/actions.ts
'use server'
import { revalidatePath } from 'next/cache'

export async function createPost(data: { title: string; body: string }) {
  const post = await db.post.create({ data })
  revalidatePath('/posts')
  return post
}

// src/app/posts/_components/create-post-form.tsx
'use client'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { createPost } from '../actions'
import { postKeys } from '@/queries/posts'

export function CreatePostForm() {
  const queryClient = useQueryClient()
  const mutation = useMutation({
    mutationFn: createPost,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: postKeys.lists() })
    },
  })

  return (
    <button
      onClick={() => mutation.mutate({ title: 'New Post', body: '...' })}
      disabled={mutation.isPending}
    >
      {mutation.isPending ? 'Creating...' : 'Create Post'}
    </button>
  )
}
```

## Optimistic Updates with Server Actions
```tsx
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), (old: Post) => ({ ...old, ...updated }))
    return { previous }
  },
  onError: (_, updated, ctx) => {
    queryClient.setQueryData(postKeys.detail(updated.id), ctx?.previous)
  },
  onSettled: (_, __, updated) => {
    queryClient.invalidateQueries({ queryKey: postKeys.detail(updated.id) })
  },
})
```

## When to Use Server Components vs TanStack Query
| Use Server Components When | Use TanStack Query When |
|---|---|
| Static or rarely-changing data | Real-time or frequently-updated data |
| SEO-critical initial content | User interactions (forms, toggles) |
| No need to refetch on client | Optimistic updates needed |
| Data is not shared across components | Data is shared across many components |
| No loading states desired | Fine-grained loading/error UI needed |

## Route Handlers (API Routes) as Query Targets
- Use `src/app/api/` route handlers as the API layer for TanStack Query fetchers
- Keep route handlers thin — just parse/validate input and call service layer
```ts
// src/app/api/posts/route.ts
import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const posts = await getPosts({ category: searchParams.get('category') })
  return NextResponse.json(posts)
}
```

## Infinite Queries (Pagination / Infinite Scroll)
```tsx
'use client'
import { useInfiniteQuery } from '@tanstack/react-query'

export function InfinitePosts() {
  const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({
    queryKey: postKeys.lists(),
    queryFn: ({ pageParam }) =>
      fetch(`/api/posts?cursor=${pageParam ?? ''}`).then(r => r.json()),
    initialPageParam: undefined as string | undefined,
    getNextPageParam: (lastPage) => lastPage.nextCursor,
  })

  const posts = data?.pages.flatMap(p => p.items) ?? []

  return (
    <div>
      {posts.map(post => <PostCard key={post.id} post={post} />)}
      <button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage}>
        {isFetchingNextPage ? 'Loading...' : 'Load More'}
      </button>
    </div>
  )
}
```

## Key Rules
- Create one `QueryClient` per request on the server side (inside Server Components)
- Create one `QueryClient` per browser session on the client (via `useState` in provider)
- Always use `HydrationBoundary` when passing server-prefetched data to client components
- Never call `fetch` inside Client Components directly — always go through `queryFn`
- Mark all components that use TanStack Query hooks with `'use client'`

© 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установок tanstack-db tanstack-skills Скилл помогает агенту работать с TanStack DB: коллекциями, живыми запросами и оптимистичными мутациями в клиентском приложении. CX Codex +1 1 600установок nextjs-cache-architecture mohamed-hossam1 Выстраивает архитектуру кеширования для Next.js 16+ App Router. Помогает внедрить директиву "use cache", собрать типизированный реестр тегов и настроить границы Suspense. CX Codex +1 5 000установок nextjs-app-router giuseppe-trisciuoglio Даёт паттерны и примеры для Next.js 16+ с App Router: от Server Components до route.ts и кэширования. CX Codex +1 3 900установок

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

nextjs Правило задаёт практики для Next.js с TypeScript и Tailwind UI. Оно пригодится для структуры проекта, компонентов, маршрутов, форм и загрузки данных. ★ 41 024звёзд репо nextjs-vercel-typescript-cursorrules-prompt-file Правило для Cursor, которое задаёт стиль кода и структуру проекта на Next.js с TypeScript, Vercel middleware и KV-базой. ★ 41 024звёзд репо nextjs-typescript-tailwind-cursorrules-prompt-file Правило для Cursor, которое задаёт агенту стандарты проекта на Next.js, TypeScript и Tailwind CSS. Пригодится, когда нужно, чтобы новый код ложился в существующую структуру. ★ 41 024звёзд репо nextjs-typescript-cursorrules-prompt-file Правило для Cursor задаёт стек Next.js с TypeScript и порядок работы агента: план, стиль кода, формат ответа. Пригодится, если вы пишете фронтенд на Next.js. ★ 41 024звёзд репо nextjs-tailwind-typescript-apps-cursorrules-prompt Правило для Cursor, которое настраивает ассистента на Next.js, Tailwind CSS и TypeScript. Оно задаёт порядок работы: сначала план в псевдокоде, потом код. ★ 41 024звёзд репо nextjs-seo-dev-cursorrules-prompt-file Правило задаёт Cursor контекст для разработки Next.js с SEO-ориентиром, комментариями и фиксированными настройками проекта. ★ 41 024звёзд репо nextjs-react-typescript-cursorrules-prompt-file Правило для Cursor, которое задаёт агенту стиль кода в проектах на Next.js 14 App Router, React и TypeScript. ★ 41 024звёзд репо nextjs-material-ui-tailwind-css-cursorrules-prompt Правило задаёт стек Next.js с TypeScript, Tailwind CSS, Material UI и App Router. Подходит для проектов, где эти библиотеки уже выбраны. ★ 41 024звёзд репо

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

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