Дефолтные опции запросов

В приложениях с большим количеством запросов быстро появляется проблема дублирования конфигурации. Одни и те же параметры начинают повторяться в каждом useQuery:

useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers,
    staleTime: 1000 * 60 * 5,
    retry: 2,
    refetchOnWindowFocus: false
})

Через некоторое время одинаковые настройки оказываются разбросаны по десяткам компонентов. Это усложняет поддержку, повышает вероятность ошибок и делает поведение запросов непредсказуемым.

TanStack Query решает эту проблему через систему дефолтных опций. Они позволяют централизованно определить базовое поведение всех запросов и мутаций.

Основная идея:

  • единая конфигурация;
  • одинаковое поведение запросов;
  • уменьшение дублирования;
  • гибкое переопределение на уровне отдельных запросов.

Создание QueryClient с дефолтными настройками

Все глобальные настройки определяются внутри QueryClient.

Базовый пример:

import { QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            staleTime: 1000 * 60,
            retry: 2
        }
    }
})

После этого все запросы автоматически получают указанные настройки.


Структура defaultOptions

Объект defaultOptions делится на две основные секции:

const queryClient = new QueryClient({
    defaultOptions: {
        queries: {},
        mutations: {}
    }
})

queries

Настройки для useQuery, useInfiniteQuery, fetchQuery, prefetchQuery.

mutations

Настройки для useMutation.


Дефолтные настройки запросов

staleTime

Параметр определяет, как долго данные считаются актуальными.

const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            staleTime: 1000 * 60 * 5
        }
    }
})

В примере данные будут считаться свежими 5 минут.

Пока данные свежие:

  • запрос не будет автоматически перезапрашиваться;
  • не произойдёт рефетч при фокусе окна;
  • не произойдёт рефетч при повторном монтировании компонента.

staleTime = 0

Значение по умолчанию.

staleTime: 0

Данные мгновенно становятся устаревшими после получения.

Это означает:

  • рефетч при возврате на вкладку;
  • рефетч при повторном монтировании;
  • агрессивную синхронизацию с сервером.

gcTime

В старых версиях параметр назывался cacheTime.

Определяет время хранения неиспользуемых данных в кеше.

const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            gcTime: 1000 * 60 * 10
        }
    }
})

После удаления последнего подписчика запрос остаётся в кеше 10 минут.

Если за это время запрос снова понадобится:

  • данные будут взяты из кеша;
  • новый запрос может не выполняться;
  • интерфейс отобразится мгновенно.

Полное удаление кеша

gcTime: 0

Кеш будет уничтожаться сразу после потери подписчиков.

Такой подход редко используется, поскольку ухудшает производительность.


retry

Количество повторных попыток при ошибке.

retry: 3

Если запрос завершится ошибкой, TanStack Query автоматически повторит его ещё 3 раза.

Отключение retry

retry: false

Полезно для:

  • авторизации;
  • валидационных ошибок;
  • запросов, где повтор бессмысленен.

retryDelay

Задержка между повторными попытками.

retryDelay: 1000

Фиксированная задержка — 1 секунда.


Функция retryDelay

retryDelay: (attempt) => {
    return Math.min(1000 * 2 ** attempt, 30000)
}

Реализуется exponential backoff.

Пример интервалов:

Попытка Задержка
1 2 сек
2 4 сек
3 8 сек
4 16 сек

Это снижает нагрузку на сервер.


refetchOnWindowFocus

Автоматический рефетч при возврате на вкладку браузера.

refetchOnWindowFocus: true

Поведение по умолчанию.

Отключение

refetchOnWindowFocus: false

Часто используется в:

  • административных панелях;
  • CRM;
  • тяжёлых интерфейсах;
  • приложениях с дорогими API-запросами.

refetchOnReconnect

Повторный запрос после восстановления интернет-соединения.

refetchOnReconnect: true

Когда соединение восстанавливается, TanStack Query автоматически синхронизирует данные.


refetchOnMount

Поведение при монтировании компонента.

refetchOnMount: true

Если данные устарели, произойдёт повторный запрос.

Возможные значения

Значение Поведение
true Рефетч при stale
false Не выполнять
“always” Всегда выполнять

refetchInterval

Интервальный polling.

refetchInterval: 5000

Запрос будет обновляться каждые 5 секунд.

Используется для:

  • чатов;
  • мониторинга;
  • биржевых данных;
  • live dashboard.

refetchIntervalInBackground

Разрешает polling в фоне.

refetchIntervalInBackground: true

Без этого polling может приостанавливаться в неактивной вкладке.


networkMode

Определяет поведение при отсутствии сети.

networkMode: 'online'

Возможные режимы

Режим Описание
online Стандартное поведение
always Игнорирует offline
offlineFirst Поддержка offline-first

enabled

Обычно задаётся локально, но может использоваться и глобально.

enabled: true

Отключение:

enabled: false

Тогда запрос не запускается автоматически.


throwOnError

Позволяет пробрасывать ошибки в Error Boundary.

throwOnError: true

Особенно полезно в React-приложениях с централизованной обработкой ошибок.


meta

Дополнительные метаданные.

meta: {
    requiresAuth: true
}

Можно использовать:

  • в middleware;
  • логировании;
  • devtools;
  • аналитике.

Дефолтные настройки мутаций

retry для mutations

const queryClient = new QueryClient({
    defaultOptions: {
        mutations: {
            retry: 1
        }
    }
})

Мутации обычно не повторяются агрессивно, поскольку это может привести к:

  • дублированию записей;
  • повторной оплате;
  • повторной отправке формы.

networkMode для mutations

mutations: {
    networkMode: 'offlineFirst'
}

Полезно для offline-first приложений.


gcTime для mutations

Мутации тоже кешируются.

mutations: {
    gcTime: 1000 * 60 * 30
}

Полный пример конфигурации

import { QueryClient } from '@tanstack/react-query'

export const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            staleTime: 1000 * 60 * 5,
            gcTime: 1000 * 60 * 30,
            retry: 2,
            retryDelay: (attempt) => {
                return Math.min(1000 * 2 ** attempt, 30000)
            },
            refetchOnWindowFocus: false,
            refetchOnReconnect: true,
            refetchOnMount: true,
            networkMode: 'online'
        },

        mutations: {
            retry: 1,
            networkMode: 'online'
        }
    }
})

Переопределение дефолтных настроек

Локальные настройки имеют приоритет над глобальными.

useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers,
    staleTime: 0
})

Даже если глобально установлен staleTime: 5 минут, здесь будет использоваться 0.


Приоритет конфигурации

Порядок приоритета:

  1. локальные настройки запроса;
  2. query defaults;
  3. global defaultOptions;
  4. встроенные настройки TanStack Query.

setQueryDefaults

TanStack Query позволяет задавать настройки для конкретных групп запросов.

queryClient.setQueryDefaults(['users'], {
    staleTime: 1000 * 60 * 10
})

Теперь все запросы с ключом users получают собственные дефолтные настройки.


Частичные queryKey

queryClient.setQueryDefaults(['posts'], {
    retry: 1
})

Будет применяться к:

['posts']
['posts', 1]
['posts', 'recent']
['posts', 'popular']

setMutationDefaults

Аналогичный механизм существует для мутаций.

queryClient.setMutationDefaults(['create-post'], {
    retry: 0
})

Глобальные стратегии кеширования

Агрессивное кеширование

queries: {
    staleTime: 1000 * 60 * 30,
    gcTime: 1000 * 60 * 60
}

Подходит для:

  • справочников;
  • редко изменяемых данных;
  • каталогов;
  • настроек.

Агрессивная синхронизация

queries: {
    staleTime: 0,
    refetchOnWindowFocus: true,
    refetchOnMount: true
}

Подходит для:

  • realtime-интерфейсов;
  • финансовых систем;
  • live dashboard;
  • совместной работы.

Offline-first стратегия

queries: {
    networkMode: 'offlineFirst',
    retry: 5
}

Используется в PWA и мобильных приложениях.


Практические рекомендации

Не устанавливать большой staleTime без необходимости

Слишком большой staleTime может приводить к отображению устаревших данных.

Проблемные сценарии:

  • данные профиля;
  • баланс счёта;
  • статусы заказов;
  • уведомления.

Осторожно с polling

refetchInterval: 1000

Запрос каждую секунду может:

  • перегружать сервер;
  • расходовать батарею;
  • создавать лишний трафик.

Не злоупотреблять retry

Повторные запросы полезны только для временных ошибок:

  • нестабильная сеть;
  • timeout;
  • кратковременная недоступность API.

Для ошибок вида:

  • 401;
  • 403;
  • 404;
  • validation error;

автоматический retry обычно бесполезен.


Разделение конфигурации по типам данных

Часто применяется несколько профилей:

queryClient.setQueryDefaults(['static'], {
    staleTime: 1000 * 60 * 60
})

queryClient.setQueryDefaults(['dynamic'], {
    staleTime: 0
})

Поведение встроенных дефолтов TanStack Query

Если настройки не указаны, библиотека использует собственные значения.

Основные встроенные дефолты:

Параметр Значение
staleTime 0
retry 3
gcTime 5 минут
refetchOnWindowFocus true
refetchOnReconnect true
refetchOnMount true

Из-за этих дефолтов TanStack Query часто кажется «слишком активным» сразу после подключения.


Централизация конфигурации

Обычно QueryClient выносится в отдельный файл:

// lib/query-client.js

import { QueryClient } from '@tanstack/react-query'

export const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            staleTime: 1000 * 60 * 5,
            retry: 2
        }
    }
})

Это позволяет:

  • поддерживать единый источник конфигурации;
  • переиспользовать настройки;
  • упрощать тестирование;
  • централизованно менять стратегию кеширования.

Влияние дефолтных опций на UX

Грамотно подобранные дефолты напрямую влияют на:

  • скорость интерфейса;
  • количество сетевых запросов;
  • отзывчивость UI;
  • потребление памяти;
  • стабильность приложения.

Неправильная конфигурация может привести к:

  • бесконечным рефетчам;
  • мерцанию интерфейса;
  • устаревшим данным;
  • чрезмерной нагрузке на API;
  • избыточному трафику.

По этой причине стратегия дефолтных настроек считается одной из ключевых частей архитектуры приложений на TanStack Query.