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

react-tanstack-router-query-cursorrules-prompt-file

Правило задаёт схему для React SPA: TanStack Router управляет маршрутами, а TanStack Query — серверными данными и кэшем. Пригодится, когда данные маршрута нужно загрузить до показа страницы.

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

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

Правило предлагает разделить обязанности: TanStack Router отвечает за маршруты, навигацию и параметры URL, а TanStack Query — за серверное состояние, кэш и асинхронные запросы. Загрузчики маршрутов заранее помещают данные в кэш; компоненты читают их через useQuery. Так можно избежать индикатора загрузки на уровне маршрута, хотя для загрузки внутри компонентов предусмотрен Suspense.

В рекомендациях есть структура каталогов routes, queries, api и lib, настройка QueryClient и Router, фабрики queryOptions, проверка параметров поиска через Zod, обработка мутаций и пример защиты маршрутов через beforeLoad. Правило также задаёт общую типизацию через TypeScript. Учитывайте, что оно не применяется автоматически: в frontmatter стоит alwaysApply: false, поэтому Cursor подключает его по контексту.

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

  • загрузить данные маршрута до рендеринга страницы
  • согласовать ключи запросов и функции загрузки
  • связать параметры URL с фильтрами и пагинацией
  • обновить кэш после создания записи
  • закрыть маршруты для неавторизованных пользователей

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

  • Настрой React SPA так, чтобы маршруты загружали данные через TanStack Query до показа страницы.
  • Свяжи параметры поиска для списка постов с ключом и функцией запроса.
  • Добавь проверку авторизации перед входом в защищённые маршруты.

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

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

.cursor/rules/react-tanstack-router-query-cursorrules-prompt-file.mdc

Во frontmatter: description, globs, alwaysApply

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

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

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

Добавь файл правила в проект по пути .cursor/rules/react-tanstack-router-query-cursorrules-prompt-file.mdc. Этот файл задаёт инструкции для Cursor.

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

Правило описывает совместное использование TanStack Router и TanStack Query в React SPA: загрузку данных через маршруты, работу с кэшем и параметрами URL.

Как правило загружает данные до отображения маршрута?

Загрузчик вызывает queryClient.ensureQueryData и помещает результат в кэш. Компонент затем использует useQuery с теми же параметрами запроса.

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

react-tanstack-router-query-cursorrules-prompt-file.mdc · CC0-1.0
---
description: "Cursor rules for React SPAs combining TanStack Router v1 and TanStack Query v5 for zero-loading-spinner routing and type-safe server state."
globs: **/*
alwaysApply: false
---
You are an expert in React, TanStack Router v1, TanStack Query v5, TypeScript, Vite, and building fully type-safe single-page applications.

# React + TanStack Router + TanStack Query Guidelines

## Architecture Overview
- TanStack Router handles all routing, URL state, and navigation
- TanStack Query manages all server state, caching, and async data
- React components are pure UI — they read from Query cache and trigger mutations
- Loaders bridge Router and Query: they prefetch into the Query cache before render
- This eliminates loading spinners for route-level data; Suspense handles component-level loading

## Project Setup
```
src/
  routes/
    __root.tsx
    index.tsx
    posts/
      index.tsx
      $postId.tsx
  queries/            ← Query definitions (queryOptions factories)
    posts.ts
    users.ts
  api/                ← API client functions (fetchers)
    posts.ts
    users.ts
  lib/
    queryClient.ts
    router.ts
  main.tsx
```

## QueryClient + Router Setup
```ts
// src/lib/queryClient.ts
import { QueryClient } from '@tanstack/react-query'

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60,
      retry: (count, error: any) => error?.status !== 404 && count < 2,
    },
  },
})
```

```tsx
// src/lib/router.ts
import { createRouter } from '@tanstack/react-router'
import { routeTree } from '../routeTree.gen'
import { queryClient } from './queryClient'

export const router = createRouter({
  routeTree,
  context: { queryClient },
  defaultPreload: 'intent',
  defaultPreloadStaleTime: 0,
})

declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}
```

```tsx
// src/main.tsx
import { RouterProvider } from '@tanstack/react-router'
import { QueryClientProvider } from '@tanstack/react-query'
import { router } from './lib/router'
import { queryClient } from './lib/queryClient'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <QueryClientProvider client={queryClient}>
    <RouterProvider router={router} context={{ queryClient }} />
  </QueryClientProvider>
)
```

## Query Definitions (queryOptions factories)
- Co-locate query key, fetcher, and staleTime in one place
- Share between Router loaders and component hooks
```ts
// src/queries/posts.ts
import { queryOptions, infiniteQueryOptions } from '@tanstack/react-query'
import { fetchPost, fetchPosts } from '../api/posts'

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 postDetailQueryOptions = (id: string) =>
  queryOptions({
    queryKey: postKeys.detail(id),
    queryFn: () => fetchPost(id),
    staleTime: 1000 * 60 * 5,
  })

export const postsListQueryOptions = (filters?: PostFilters) =>
  queryOptions({
    queryKey: postKeys.list(filters),
    queryFn: () => fetchPosts(filters),
    staleTime: 1000 * 60,
  })
```

## Router Loader + Query Integration
- Loaders call `queryClient.ensureQueryData` — populates cache, renders immediately without spinner
- Components then call `useQuery` with the same options — reads from cache synchronously
```tsx
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { postDetailQueryOptions } from '../../queries/posts'

export const Route = createFileRoute('/posts/$postId')({
  loader: ({ context: { queryClient }, params }) =>
    queryClient.ensureQueryData(postDetailQueryOptions(params.postId)),

  errorComponent: ({ error }) => <ErrorMessage error={error} />,
  pendingComponent: PostSkeleton,
  component: PostDetail,
})

function PostDetail() {
  const { postId } = Route.useParams()
  // data is already in cache from loader — no loading state
  const { data: post } = useQuery(postDetailQueryOptions(postId))

  return <article><h1>{post!.title}</h1></article>
}
```

## Search Params + Query Integration
- Use TanStack Router search params as the source of truth for filter/pagination state
- Pass search params into queryOptions to drive query key and fetcher
```tsx
// src/routes/posts/index.tsx
import { createFileRoute, Link } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
import { postsListQueryOptions } from '../../queries/posts'

const searchSchema = z.object({
  page: z.number().int().min(1).default(1),
  category: z.string().optional(),
})

export const Route = createFileRoute('/posts/')({
  validateSearch: searchSchema,
  loader: ({ context: { queryClient }, location: { search } }) =>
    queryClient.ensureQueryData(postsListQueryOptions(search)),
  component: PostsList,
})

function PostsList() {
  const search = Route.useSearch()
  const navigate = Route.useNavigate()
  const { data: posts } = useQuery(postsListQueryOptions(search))

  return (
    <div>
      {posts?.map(post => (
        <Link key={post.id} to="/posts/$postId" params={{ postId: post.id }}>
          {post.title}
        </Link>
      ))}
      <button onClick={() => navigate({ search: { ...search, page: search.page + 1 } })}>
        Next Page
      </button>
    </div>
  )
}
```

## Mutations
```tsx
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { postKeys } from '../../queries/posts'

function CreatePostForm() {
  const queryClient = useQueryClient()
  const navigate = useNavigate()

  const mutation = useMutation({
    mutationFn: createPost,
    onSuccess: (newPost) => {
      // Populate detail cache immediately
      queryClient.setQueryData(postKeys.detail(newPost.id), newPost)
      // Invalidate list queries
      queryClient.invalidateQueries({ queryKey: postKeys.lists() })
      // Navigate to new post (no loading — cache is warm)
      navigate({ to: '/posts/$postId', params: { postId: newPost.id } })
    },
  })

  return (/* form JSX */)
}
```

## Authentication Pattern
```tsx
// src/routes/__root.tsx
import { createRootRouteWithContext } from '@tanstack/react-router'

export interface RouterContext {
  queryClient: QueryClient
  auth: { isAuthenticated: boolean; user: User | null }
}

export const Route = createRootRouteWithContext<RouterContext>()({
  component: RootLayout,
})

// src/routes/_auth.tsx (pathless layout for protected routes)
export const Route = createFileRoute('/_auth')({
  beforeLoad: ({ context }) => {
    if (!context.auth.isAuthenticated) {
      throw redirect({ to: '/login', search: { redirect: location.pathname } })
    }
  },
})
```

## Prefetching on Hover
```tsx
function PostCard({ post }: { post: Post }) {
  const queryClient = useQueryClient()
  return (
    <Link
      to="/posts/$postId"
      params={{ postId: post.id }}
      onMouseEnter={() => queryClient.prefetchQuery(postDetailQueryOptions(post.id))}
    >
      {post.title}
    </Link>
  )
}
```

## DevTools (Development Only)
```tsx
// In __root.tsx
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

// Inside component
{import.meta.env.DEV && (
  <>
    <TanStackRouterDevtools position="bottom-left" />
    <ReactQueryDevtools buttonPosition="bottom-right" />
  </>
)}
```

## Key Rules
- Always define `queryOptions` outside of components — not inline in `useQuery()`
- Never use `useEffect` to fetch data — use loaders or `useQuery`
- Always type router context — `declare module '@tanstack/react-router'` registration is required
- Search params are the only source of truth for URL-driven filter state
- Mutations should `setQueryData` + `invalidateQueries`, not just invalidate, for instant UI feedback

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

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

Все правила IDE по теме «Фронтенд и UI» →
winui3 официальный github Правило задаёт рекомендации для WinUI 3 и Windows App SDK: от XAML и потоков до окон и MVVM. Пригодится, чтобы Copilot учитывал особенности настольных приложений Windows. ★ 40 451звёзд репо vue официальный github Правило задаёт Copilot стандарты Vue 3: Composition API, <script setup>, реактивность, Pinia и Vue Router. Пригодится, когда агент пишет компоненты в вашем стиле. ★ 40 451звёзд репо tanstack-start-shadcn-tailwind официальный github Правило задаёт Copilot стек TanStack Start, Shadcn/ui и Tailwind CSS и требует валидировать внешние данные через Zod. ★ 40 451звёзд репо tailwind-v4-vite официальный github Правило помогает подключить Tailwind CSS v4 к проекту на Vite через официальный плагин. Пригодится и для новой установки, и при переходе с v3. ★ 40 451звёзд репо svelte официальный github Направляет GitHub Copilot на стандарты Svelte 5 и SvelteKit 2: руны вместо старых сторов, типизация компонентов и безопасная работа с SSR. ★ 40 451звёзд репо power-bi-custom-visuals-development официальный github Правило для GitHub Copilot, которое подсказывает агенту, как писать кастомные визуалы Power BI на React, D3.js и TypeScript. ★ 40 451звёзд репо

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

Весь набор →
react-zustand-cursorrules-prompt-file Инструкция для Cursor по работе со стейт-менеджером Zustand в React и TypeScript. Задаёт архитектуру сторов, защищает от лишних ререндеров и отсекает серверный кэш от клиентских данных. ★ 41 024звёзд репо react-typescript-symfony-cursorrules-prompt-file Правило Cursor, которое настраивает ассистента на чистый код в стеке React, TypeScript, PHP, Symfony и Docker. ★ 41 024звёзд репо react-typescript-nextjs-nodejs-cursorrules-prompt- Правило для Cursor задаёт стиль кода на React, TypeScript, Next.js 14 и Node.js: функциональные компоненты, RORO, минимум use client. ★ 41 024звёзд репо react-tanstack-router-query Настраивает связку TanStack Router v1 и TanStack Query v5 в React-проектах для загрузки данных в роутере без спиннеров ожидания. ★ 41 024звёзд репо react-styled-components-cursorrules-prompt-file Правило для Cursor, которое задаёт агенту стиль кода на React со styled-components: функциональные компоненты, тема через ThemeProvider, папка styles. ★ 41 024звёзд репо react-router-v7 Задаёт стандарты React Router v7 для маршрутов, загрузчиков, мутаций и типизации в файлах TypeScript и конфигах проекта. ★ 41 024звёзд репо react-redux-typescript-cursorrules-prompt-file Правило задаёт стиль React-кода с Redux и TypeScript: функциональные компоненты, типизированные хуки и структуру проекта. Подключается к Cursor. ★ 41 024звёзд репо react-query-cursorrules-prompt-file Правило для Cursor, которое задаёт агенту соглашения по React Query: где держать QueryClient, как называть хуки и ключи запросов. ★ 41 024звёзд репо

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

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