К основному содержанию
скилл CX Codex

react-query — скилл для Claude Code: правила работы с React Query

Задаёт агенту правила работы с React Query: кэширование, фоновые обновления, инвалидация запросов и оптимистичные апдейты.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add Mindrally/skills --skill react-query -a claude-code
Открыть на GitHub

Что делает react-query

Скилл объясняет агенту, как устроен React Query (он же TanStack Query), и заставляет его писать код по этим правилам. Серверные данные идут через useQuery и useMutation, а не через useState. Клиентское состояние остаётся за React Context и useReducer или за Zustand — в скилле есть примеры обоих вариантов.

Внутри — структура проекта с папками queries.ts и mutations.ts рядом с компонентами, настройка QueryClientProvider со staleTime, cacheTime и retry, шаблоны зависимых и пагинированных запросов, бесконечная прокрутка через useInfiniteQuery. Отдельный блок про оптимистичные обновления: отмена запросов, сохранение предыдущего значения и откат в onError. Ключи запросов советует собирать в один объект queryKeys с фабриками вместо строк на месте.

Скилл написан под старый пакет react-query, а не под @tanstack/react-query. Если в проекте уже стоит TanStack Query v5, примеры придётся править: там нет cacheTime, а keepPreviousData заменён на placeholderData. Это повод проверить версию до того, как агент начнёт копировать код из скилла.

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

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

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

  • настрой React Query в проекте и вынеси хуки запросов в отдельные файлы
  • добавь оптимистичное обновление для редактирования профиля
  • перепиши загрузку списка пользователей на useInfiniteQuery

Как установить react-query

1Через Skills CLI (Vercel)

npx skills add Mindrally/skills --skill react-query -a claude-code

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

~/.claude/skills/react-query/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/react-query/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

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

postgresql-best-practices Скилл с правилами разработки на PostgreSQL: типы данных, схема, индексы, разбор планов запросов и обслуживание базы. CX Codex +1 1 500установок tailwindcss Задаёт агенту стиль работы с TailwindCSS: утилитарные классы прямо в разметке, мобильный первым, тёмная тема через вариант dark:. CX Codex +1 1 500установок data-analysis-jupyter Задаёт правила для анализа данных, построения графиков и оформления блокнотов Jupyter с помощью pandas, numpy, matplotlib и seaborn. Помогает писать воспроизводимый код без лишних циклов. CX Codex +1 1 500установок express-typescript Правила для агента, который пишет API на Express.js и TypeScript: структура проекта, middleware, валидация и безопасность. CX Codex +1 1 400установок redux-toolkit Набор правил по архитектуре Redux Toolkit для React и Next.js на TypeScript. Пригодится при настройке хранилища, типизации хуков и написании слайсов. CX Codex +1 1 300установок front-end-developer Скилл превращает агента в старшего фронтенд-разработчика: React, Next.js, TypeScript, Tailwind, доступность. Пригодится, когда нужно писать компоненты, а не обсуждать их. CX Codex +1 1 300установок lua Задаёт агенту правила письма на Lua: таблицы, метатаблицы, обработка ошибок, игровой цикл и работа с памятью. Пригодится, если проект на Lua или Love2D. CX Codex +1 1 300установок tauri-development Скилл задаёт правила разработки десктопных программ на Tauri. Он настраивает связку Rust-бэкенда с фронтендом на TypeScript, React или Next.js. CX Codex +1 1 300установок

Похожие

tanstack-query-best-practices DeckardGer Свод правил TanStack Query для React: ключи запросов, кеш, мутации, SSR. Подключается к Claude Code, Codex, Cursor и Copilot — чтобы загрузка данных в проекте шла по одной схеме. CX Codex +1 12 800установок tanstack-query tanstack-skills Скилл подсказывает агенту, как работать с TanStack Query v5: кэширование, инвалидация, мутации и оптимистичные обновления. CX Codex +1 9 900установок react-data-fetching patterns.dev Учит агента правильной загрузке данных в React: параллельные запросы, кэш, дедупликация, Suspense. Пригодится, когда компоненты тянут данные через useEffect и fetch. CX Codex +1 1 100установок react-query-cursorrules-prompt-file PatrickJS Правило для Cursor, которое задаёт агенту соглашения по React Query: где держать QueryClient, как называть хуки и ключи запросов. ★ 41 011звёзд репо nextjs-data-fetching giuseppe-trisciuoglio Скилл даёт готовые паттерны выборки данных в Next.js App Router: от серверных компонентов и ISR до интеграции с SWR и React Query. CX Codex +1 3 700установок tanstack-query-v5-cursorrules-prompt-file PatrickJS Правило для Cursor, которое задаёт агенту стиль работы с TanStack Query v5: ключи запросов, мутации, оптимистичные обновления, Suspense и префетчинг. ★ 41 011звёзд репо

Рядом в теме «Фронтенд и UI»

Всё по теме «Фронтенд и UI» →

Вопросы о react-query

Как установить react-query в Claude?

Выполните npx skills add Mindrally/skills --skill react-query -a claude-code. Скилл окажется в ~/.claude/skills/react-query/SKILL.md.

Что делает скилл react-query?

Даёт агенту правила работы с React Query: запросы, мутации, кэширование, инвалидация и оптимистичные обновления. Агент опирается на них, когда пишет код загрузки данных в React.

С какими версиями React Query работает скилл?

Примеры построены на пакете react-query со старым API: cacheTime, keepPreviousData. Для TanStack Query v5 их нужно переписать.

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

SKILL.md · Apache-2.0
---
name: react-query
description: Guidelines for using React Query for data fetching, caching, and server state synchronization in React applications
metadata:
  maintainer: Mindrally
  source: https://github.com/Mindrally/skills
---

# React Query Best Practices

You are an expert in React Query, TypeScript, and React development. React Query (now TanStack Query) simplifies data fetching logic with built-in caching, background updates, and stale data management.

## Core Principles

- Use React Query for all data fetching and caching
- Leverage React Query's built-in state management instead of `useState` for server data
- Use React Context and `useReducer` for managing client-side global state
- Avoid excessive API calls through proper caching strategies
- Always handle loading states and errors properly

## Project Structure

```
src/
  components/
    [Feature]/
      index.tsx
      queries.ts           # Feature-specific query hooks
      mutations.ts         # Feature-specific mutation hooks
  hooks/
    useAuth.ts
    useApi.ts
  services/
    api/
      client.ts            # Axios/fetch configuration
      users.ts             # User API functions
      posts.ts             # Post API functions
  providers/
    ReactQueryProvider.tsx
  types/
    index.ts
```

## Setup

### Provider Configuration

```typescript
// providers/ReactQueryProvider.tsx
import { QueryClient, QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,    // 5 minutes
      cacheTime: 30 * 60 * 1000,   // 30 minutes
      retry: 2,
      refetchOnWindowFocus: true,
    },
  },
});

export function ReactQueryProvider({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>
      {children}
      <ReactQueryDevtools />
    </QueryClientProvider>
  );
}
```

## Query Patterns

### Basic Query Hook

```typescript
import { useQuery } from 'react-query';
import { fetchUser, User } from '@/services/api/users';

export function useUser(userId: string) {
  return useQuery<User, Error>(
    ['user', userId],
    () => fetchUser(userId),
    {
      enabled: !!userId,
      staleTime: 1000 * 60 * 10, // 10 minutes
    }
  );
}
```

### Query with Error Handling

Services should throw user-friendly errors that React Query can catch and display:

```typescript
// services/api/users.ts
export async function fetchUser(userId: string): Promise<User> {
  const response = await fetch(`/api/users/${userId}`);

  if (!response.ok) {
    // Throw user-friendly error message
    throw new Error('Unable to load user profile. Please try again.');
  }

  return response.json();
}

// Component usage
function UserProfile({ userId }: { userId: string }) {
  const { data: user, isLoading, error } = useUser(userId);

  if (isLoading) return <LoadingSpinner />;
  if (error) return <ErrorMessage message={error.message} />;

  return <ProfileCard user={user} />;
}
```

### Dependent Queries

```typescript
function useUserWithPosts(userId: string) {
  const userQuery = useUser(userId);

  const postsQuery = useQuery(
    ['posts', userId],
    () => fetchUserPosts(userId),
    {
      enabled: !!userQuery.data,
    }
  );

  return { userQuery, postsQuery };
}
```

### Paginated Queries

```typescript
function usePaginatedUsers(page: number, limit: number = 10) {
  return useQuery(
    ['users', 'list', { page, limit }],
    () => fetchUsers({ page, limit }),
    {
      keepPreviousData: true,
    }
  );
}
```

### Infinite Scroll

```typescript
import { useInfiniteQuery } from 'react-query';

function useInfiniteUsers() {
  return useInfiniteQuery(
    ['users', 'infinite'],
    ({ pageParam = 1 }) => fetchUsers({ page: pageParam }),
    {
      getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined,
    }
  );
}
```

## Mutation Patterns

### Basic Mutation

```typescript
import { useMutation, useQueryClient } from 'react-query';

function useCreateUser() {
  const queryClient = useQueryClient();

  return useMutation(createUser, {
    onSuccess: () => {
      queryClient.invalidateQueries(['users']);
    },
    onError: (error: Error) => {
      toast.error(error.message);
    },
  });
}
```

### Optimistic Updates

```typescript
function useUpdateUser() {
  const queryClient = useQueryClient();

  return useMutation(updateUser, {
    onMutate: async (updatedUser) => {
      await queryClient.cancelQueries(['user', updatedUser.id]);

      const previousUser = queryClient.getQueryData(['user', updatedUser.id]);

      queryClient.setQueryData(['user', updatedUser.id], updatedUser);

      return { previousUser };
    },
    onError: (err, updatedUser, context) => {
      if (context?.previousUser) {
        queryClient.setQueryData(['user', updatedUser.id], context.previousUser);
      }
    },
    onSettled: (data, error, updatedUser) => {
      queryClient.invalidateQueries(['user', updatedUser.id]);
    },
  });
}
```

## State Management Integration

### Combining with Context/Reducer

Use React Query for server state and Context/Reducer for client state:

```typescript
// Client state with Context
const AppStateContext = createContext<AppState | undefined>(undefined);
const AppDispatchContext = createContext<Dispatch<Action> | undefined>(undefined);

function AppProvider({ children }: { children: React.ReactNode }) {
  const [state, dispatch] = useReducer(appReducer, initialState);

  return (
    <AppStateContext.Provider value={state}>
      <AppDispatchContext.Provider value={dispatch}>
        {children}
      </AppDispatchContext.Provider>
    </AppStateContext.Provider>
  );
}

// Server state with React Query
function UserDashboard() {
  const { theme } = useAppState();         // Client state
  const { data: user } = useUser(userId);  // Server state

  return <Dashboard theme={theme} user={user} />;
}
```

### Combining with Zustand (Alternative)

```typescript
import { create } from 'zustand';

// Client state store
const useStore = create((set) => ({
  theme: 'light',
  setTheme: (theme) => set({ theme }),
}));

// Component using both
function App() {
  const theme = useStore((state) => state.theme);
  const { data: user } = useUser(userId);

  return <Layout theme={theme} user={user} />;
}
```

## Performance Optimization

### Query Key Best Practices

```typescript
// Structured query keys
const queryKeys = {
  users: {
    all: ['users'] as const,
    lists: () => [...queryKeys.users.all, 'list'] as const,
    list: (filters: Filters) => [...queryKeys.users.lists(), filters] as const,
    details: () => [...queryKeys.users.all, 'detail'] as const,
    detail: (id: string) => [...queryKeys.users.details(), id] as const,
  },
};
```

### Selective Subscriptions

```typescript
// Only subscribe to user name changes
function useUserName(userId: string) {
  return useUser(userId, {
    select: (user) => user.name,
  });
}
```

### Prefetching

```typescript
function UserListItem({ userId }: { userId: string }) {
  const queryClient = useQueryClient();

  const handleMouseEnter = () => {
    queryClient.prefetchQuery(
      ['user', userId],
      () => fetchUser(userId),
      { staleTime: 60000 }
    );
  };

  return (
    <li onMouseEnter={handleMouseEnter}>
      <Link to={`/users/${userId}`}>View Profile</Link>
    </li>
  );
}
```

## Error Handling Patterns

### Global Error Handler

```typescript
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      onError: (error: Error) => {
        console.error('Query error:', error);
      },
    },
    mutations: {
      onError: (error: Error) => {
        toast.error(error.message);
      },
    },
  },
});
```

### Error Boundaries

```typescript
import { QueryErrorResetBoundary } from 'react-query';
import { ErrorBoundary } from 'react-error-boundary';

function App() {
  return (
    <QueryErrorResetBoundary>
      {({ reset }) => (
        <ErrorBoundary
          onReset={reset}
          fallbackRender={({ error, resetErrorBoundary }) => (
            <div>
              <p>Something went wrong: {error.message}</p>
              <button onClick={resetErrorBoundary}>Try again</button>
            </div>
          )}
        >
          <UserProfile />
        </ErrorBoundary>
      )}
    </QueryErrorResetBoundary>
  );
}
```

## Key Conventions

1. Use React Query DevTools to inspect cache and track query status
2. Group react-query hooks within feature-specific directories (feature-based organization)
3. Always handle errors properly with user-friendly messages and retry options
4. Fetch only required data - use API parameters to reduce data transfer
5. Avoid deeply nesting queries - flatten when possible for better performance
6. Use local state for component-specific data, global state for shared data
7. Leverage React Query's built-in caching and state management capabilities

## Anti-Patterns to Avoid

- Do not use `useEffect` for data fetching
- Do not store server data in `useState`
- Do not forget loading and error state handling
- Do not create queries without proper cache invalidation strategies
- Do not skip the `enabled` option for conditional queries
- Do not ignore TypeScript types for query responses

© Mindrally · Apache-2.0 · Mindrally/skills

Смотрите также

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

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