Гид по технологиям

TanStack Query (React Query): руководство по эффективному извлечению данных в React

5 min read React Обновлено 11 Apr 2026
TanStack/React Query — быстрое извлечение данных в React
TanStack/React Query — быстрое извлечение данных в React

Ноутбук на столе с открытой панелью данных на экране.

Что такое TanStack Query (коротко)

TanStack Query — это клиентская библиотека для получения, кеширования и синхронизации серверных данных в React. Она абстрагирует большую часть обычного boilerplate вокруг fetch/axios, предоставляет декларативные хуки и готовые стратегии для повторных попыток, рефетча и оптимистичных обновлений.

Определение: useQuery — хук для чтения/кеширования, useMutation — хук для модификации данных (POST/PUT/DELETE). Ключевая сущность — QueryClient, который управляет состоянием кеша и политиками.

Установка и первоначальная настройка

Установите библиотеку через npm или yarn:

npm i @tanstack/react-query

или

yarn add @tanstack/react-query

После установки оберните корневой компонент приложения в QueryClientProvider и создайте экземпляр QueryClient. Пример корректной и минимальной инициализации (React 18+):

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

ReactDOM.createRoot(document.getElementById('root')).render(
  
    
      
    
  
)

Важно: QueryClientProvider должен быть выше компонентов, которые пользуются хуками tanstack/react-query.

Основные понятия (одной строкой)

  • QueryKey — уникальный идентификатор запроса. Может быть строкой, массивом или объектом.
  • QueryFn — функция, возвращающая Promise с данными.
  • staleTime — время (мс), в течение которого данные считаются «свежими».
  • cacheTime — время (мс), по истечении которого неиспользуемый кеш удаляется.

useQuery — получение и кеширование данных

useQuery предназначен для чтения данных и автоматического кеширования. Он принимает объект с параметрами или упрощённый синтаксис. Пример с axios:

import React from 'react'
import axios from 'axios'
import { useQuery } from '@tanstack/react-query'

function Home() {
  const postQuery = useQuery({
    queryKey: ['posts'],
    queryFn: async () => {
      const response = await axios.get('https://jsonplaceholder.typicode.com/posts')
      return response.data
    },
    staleTime: 1000 * 60, // данные считаются свежими 1 мин
    cacheTime: 1000 * 60 * 5, // кеш хранится 5 мин если никто не использует
  })

  if (postQuery.isLoading) return 

Загрузка…

if (postQuery.isError) return

Ошибка при загрузке данных

return (

Home

{postQuery.data.map(item => (

{item.title}

))}
) } export default Home

Что важно знать:

  • postQuery возвращает состояние: isLoading, isError, isSuccess, data, error и др.
  • queryKey обязателен для идентификации и инвалидации.
  • queryFn получает аргумент с полем queryKey: useful для динамических запросов.

Пример доступа к queryKey внутри queryFn:

useQuery({
  queryKey: ['posts', { userId: 2 }],
  queryFn: async ({ queryKey }) => {
    // queryKey === ['posts', { userId: 2 }]
    const [, params] = queryKey
    const resp = await fetch(`https://api.example.com/posts?userId=${params.userId}`)
    return resp.json()
  }
})

Управление «устаревшими» данными и рефетчем

TanStack Query по умолчанию делает рефетч при фокусе окна и при восстановлении сети. Дополнительные настройки:

  • staleTime — время в миллисекундах, пока данные считаются свежими. После этого при обращении может инициироваться рефетч.
  • refetchInterval — периодический рефетч (мс). Можно поставить false для отключения.
  • refetchOnWindowFocus — рефетчать при фокусе окна (true/false).
  • cacheTime — сколько держать кеш, если на него нет подписчиков.

Примеры:

useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  staleTime: 1000 * 30, // 30 сек
  refetchInterval: 1000 * 60 * 5, // каждые 5 минут
  refetchOnWindowFocus: true,
})

Important: слишком частый рефетч ухудшит производительность и расход трафика. Настраивайте под характер данных (часто меняются / редко меняются).

useMutation — создание и изменение данных

useMutation используется для POST/PUT/DELETE операций. Он не кеширует автоматически данные (это мутации), но позволяет запускать побочные эффекты (invalidateQueries) и реализовывать оптимистичные обновления.

Полный пример компонента AddPost с useMutation и оптимистичным обновлением:

import React from 'react'
import axios from 'axios'
import { useMutation, useQueryClient } from '@tanstack/react-query'

function AddPost() {
  const [post, setPost] = React.useState({ title: '' })
  const queryClient = useQueryClient()

  const newPostMutation = useMutation({
    mutationFn: async (newPost) => {
      const response = await axios.post('https://jsonplaceholder.typicode.com/posts', newPost)
      return response.data
    },
    onMutate: async (newPost) => {
      // Отключаем автоматический рефетч и делаем оптимистичное обновление кеша
      await queryClient.cancelQueries(['posts'])
      const previous = queryClient.getQueryData(['posts'])
      queryClient.setQueryData(['posts'], old => [...(old || []), { id: Date.now(), ...newPost }])
      return { previous }
    },
    onError: (err, newPost, context) => {
      // Откат в случае ошибки
      queryClient.setQueryData(['posts'], context.previous)
    },
    onSettled: () => {
      // После завершения (успех или ошибка) инвалидация кеша для получения актуальных данных
      queryClient.invalidateQueries(['posts'])
    }
  })

  function handleChange(e) {
    setPost(prev => ({ ...prev, [e.target.name]: e.target.value }))
  }

  async function handleSubmit(e) {
    e.preventDefault()
    newPostMutation.mutate({ title: post.title })
    setPost({ title: '' })
  }

  return (
    
{newPostMutation.isLoading &&

Отправка…

} {newPostMutation.isError &&

Ошибка при отправке

}
) } export default AddPost

Пояснения:

  • onMutate — используется для оптимистичного обновления кеша.
  • onError — откат изменений при ошибке.
  • onSettled/onSuccess — инвалидация или обновление других запросов.

Распространённые опции и паттерны

  • retry: число повторных попыток (по умолчанию 3). Можно поставить false.
  • enabled: условное включение запроса (например, только когда есть id).
  • select: преобразование данных перед выдачей компоненту.
  • placeholderData: временные данные, пока основная загрузка не вернулась.

Пример условного запроса:

useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
  enabled: !!userId,
})

Альтернативы и когда React Query не подходит

  • SWR (Vercel) — альтернативная библиотека с похожими целями, проще по API в некоторых сценариях.
  • Apollo Client — если основная нагрузка — GraphQL; предоставляет более тесную интеграцию с GraphQL‑фичами (фрагменты, cache policies).
  • Простые fetch/axios + локальный стейт — подходит для очень маленьких приложений и простых однократных запросов.

Когда не стоит использовать TanStack Query:

  • Если приложение не делает запросов к серверу (статический сайт без обновлений).
  • Если нужна экстремально тонкая оптимизация для специфичных протоколов (требуется специальный клиент).

Ментальные модели и эвристики

  • Кеш = источник правды для UI (read from cache, write via mutations + invalidate).
  • Никаких «глобальных» fetch-циклов вручную: хуки управляют жизненным циклом.
  • Делайте данные «достаточно свежими»: для критичных данных ставьте короткий staleTime; для редко меняющихся — длинный.

Правило большого пальца: если данные отображаются в несколько мест — используйте queryKey и кеш, чтобы избежать дублированных fetch.

Практическая методология внедрения (чеклист)

  1. Установить @tanstack/react-query и добавить QueryClientProvider.
  2. Определить ключи запросов (queryKey) и договориться о формате (например, [‘posts’, { userId }]).
  3. Для каждого запроса создать useQuery с подходящими staleTime, cacheTime.
  4. Для мутаций использовать useMutation; для атомарных изменений — onMutate/onError/onSettled.
  5. Написать тесты/кейс‑тесты для успешного запроса, ошибки и повторных попыток.
  6. Наблюдать поведение в проде: трафик, частота рефетчей, UX.

Критерии приёмки

  • Данные отображаются при первом рендере и при сетевых изменениях.
  • При создании/удалении/обновлении данных UI корректно отражает состояние (оптимистично или после успешного ответа).
  • Ошибки показываются пользователю и логируются.
  • Нет лишних повторных запросов при переходах между страницами.

Сравнение: useQuery vs useMutation (быстрая шпаргалка)

  • useQuery: чтение, кеширование, авто‑рефетч. Возвращает { data, isLoading, isError, isSuccess }.
  • useMutation: запись/изменение, не кеширует автоматически. Позволяет оптимистичные обновления и откаты.

Совместимость и миграция

  • TanStack Query поддерживает React 16.8+ (хуки). Для Next.js используйте подходы SSR/SSG: hydrate состояние на клиенте через dehydrate/hydrate helper из @tanstack/react-query.
  • При миграции с SWR проверьте различия в lifecycle (рефетч при фокусе по умолчанию) и API.

Мини‑чеклист безопасности и приватности

  • Не храните в кеше чувствительные личные данные дольше, чем нужно; настраивайте cacheTime.
  • Для данных, подлежащих удалению по GDPR, инвалируйте и удаляйте их из кеша на стороне клиента при запросе на удаление.

Быстрая шпаргалка (cheat sheet)

  • Создать клиент: new QueryClient()
  • Провайдер:
  • Чтение: useQuery({ queryKey, queryFn, staleTime, cacheTime })
  • Запись: useMutation({ mutationFn, onMutate, onError, onSettled })
  • Управление кешем: useQueryClient().invalidateQueries([‘key’])

Пример диаграммы принятия решения (Mermaid)

flowchart TD
  A[Нужно получить данные?] -->|Да| B{Есть уникальный queryKey?}
  B -->|Да| C[Использовать useQuery]
  B -->|Нет| D[Определить ключ 'напр. ['resource', id]']
  A -->|Нет| E[Нет запросов — не использовать React Query]
  C --> F{Нужно изменить данные?}
  F -->|Да| G[Использовать useMutation + invalidateQueries]
  F -->|Нет| H[Обычный read-only flow]

Примеры типичных ошибок и как их исправить

  • Проблема: бесконечные рефетчи — проверьте refetchInterval и callback внутри queryFn, не меняющий queryKey каждую итерацию.
  • Проблема: stale данные после мутации — используйте invalidateQueries или onSuccess для обновления кеша.
  • Проблема: запросы выполняются слишком часто — увеличьте staleTime или отключите refetchOnWindowFocus.

Резюме

TanStack Query значительно упрощает работу с асинхронными данными в React: он управляет кешем, рефетчем, стратегиями повторных попыток и даёт мощные точки расширения (optimistic updates, query invalidation). При грамотной конфигурации вы получаете более отзывчивый UI и меньше сетевого шума.

Notes: начните с простых настроек по умолчанию и добавляйте тонкую настройку staleTime/refetchInterval по мере понимания характера ваших данных.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Jamboard в Google Meet: пошаговое руководство
Совещания

Jamboard в Google Meet: пошаговое руководство

Octolapse — таймлапсы 3D-печати: настройка
3D-печать

Octolapse — таймлапсы 3D-печати: настройка

Как полностью удалить программы в Windows
Windows

Как полностью удалить программы в Windows

Массово повернуть фото на iPhone
Фото

Массово повернуть фото на iPhone

Как обновить Nintendo Switch
Гайды

Как обновить Nintendo Switch

Клонирование Windows 10: Macrium Reflect — руководство
Руководства

Клонирование Windows 10: Macrium Reflect — руководство