Работа офлайн в клиентских приложениях перестала быть исключением и превратилась в стандартное требование для многих интерфейсов. TanStack Query предоставляет набор механизмов, которые позволяют строить устойчивые к потере сети системы данных без ручного управления состоянием загрузки и синхронизации.
Ключевая идея офлайн-стратегий в TanStack Query заключается в том, что кэш становится основным источником истины на время отсутствия соединения, а синхронизация с сервером откладывается до восстановления сети.
TanStack Query сохраняет результаты запросов в кэше, привязанном к
ключам queryKey. При отсутствии сети поведение приложения
определяется комбинацией нескольких параметров:
Основной механизм устойчивости — использование ранее загруженных данных вместо попыток немедленного повторного запроса.
Два параметра играют центральную роль в поведении данных:
staleTime определяет период, в течение которого данные считаются актуальными.
При офлайн-сценариях увеличение staleTime приводит к тому, что приложение не пытается сразу обновлять данные при каждом монтировании компонента.
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 1000 * 60 * 5
})
В офлайн-режиме это снижает количество бесполезных попыток синхронизации.
gcTime (garbage collection time) управляет временем хранения неиспользуемых данных в кэше.
При корректной настройке gcTime можно обеспечить сохранность данных между сессиями, если используется persistence слой.
Для полноценной офлайн-поддержки используется персистентный кэш. TanStack Query позволяет сохранять состояние кэша в внешнее хранилище.
Типичная стратегия включает:
Базовая интеграция выглядит через persistQueryClient:
import { QueryClient } from '@tanstack/react-query'
import { persistQueryClient } from '@tanstack/react-query-persist-client'
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'
const queryClient = new QueryClient()
const persister = createSyncStoragePersister({
storage: window.localStorage
})
persistQueryClient({
queryClient,
persister
})
При таком подходе данные переживают перезагрузку страницы и отсутствие сети.
TanStack Query не содержит встроенного детектора сети как обязательного компонента, но его поведение адаптируется к ошибкам fetch.
Типичные сценарии:
Конфигурация retry критична:
useQuery({
queryKey: ['profile'],
queryFn: fetchProfile,
retry: (failureCount, error) => {
if (!navigator.onLine) return false
return failureCount < 3
}
})
Отключение retry при офлайн-состоянии предотвращает лишние попытки.
Для корректной работы офлайн-режима важно синхронизировать состояние сети с поведением TanStack Query.
Обычно используется браузерное API:
И принудительное управление queryClient:
window.addEventListener('online', () => {
queryClient.resumePausedMutations()
queryClient.invalidateQueries()
})
При восстановлении сети выполняются:
Наиболее сложный аспект офлайн-архитектуры связан с мутациями данных.
TanStack Query позволяет реализовать очередь изменений через:
useMutation({
mutationFn: updateTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries(['todos'])
const previous = queryClient.getQueryData(['todos'])
queryClient.setQueryData(['todos'], old =>
old.map(t => t.id === newTodo.id ? newTodo : t)
)
return { previous }
},
onError: (err, newTodo, context) => {
queryClient.setQueryData(['todos'], context.previous)
}
})
При отсутствии сети изменения могут быть применены локально и откатаны при ошибке.
Для полноценной офлайн-работы применяется паттерн очереди:
TanStack Query не предоставляет полноценную очередь “из коробки”, но интегрируется с кастомными persistence слоями.
Пример логики:
После перехода в online режим важно не перегружать сервер и интерфейс.
TanStack Query использует:
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnReconnect: true,
refetchOnWindowFocus: false
}
}
})
Такое поведение позволяет синхронизировать данные без лишнего трафика.
В приложениях SSR или гибридных системах важную роль играет hydration.
Сервер может передать предварительно загруженные данные, а клиент продолжает работу офлайн с уже заполненным кэшем.
import { dehydrate, HydrationBoundary } from '@tanstack/react-query'
const dehydratedState = dehydrate(queryClient)
При восстановлении кэша офлайн-режим получает стартовые данные без необходимости сети.
Не все данные одинаково подходят для офлайн-доступа. Практика делит их на категории:
Для каждой категории задаются разные параметры:
При восстановлении сети основная задача — привести локальный кэш в соответствие с сервером.
Используются механизмы:
queryClient.invalidateQueries({
queryKey: ['todos']
})
Частичная инвалидация позволяет избежать полной перезагрузки данных.
Офлайн-режим неизбежно приводит к конфликтам между локальными и серверными изменениями.
Основные стратегии:
TanStack Query предоставляет инструменты для реализации любого подхода через onSuccess и onError мутаций, а также через ручное управление кэшем.
Retry-логика требует особого внимания в офлайн-режиме. Без ограничений она приводит к:
Оптимальная стратегия:
События видимости вкладки влияют на стратегию обновления данных.
useQuery({
queryKey: ['messages'],
queryFn: fetchMessages,
refetchOnWindowFocus: true
})
При возвращении пользователя в приложение данные синхронизируются автоматически, если сеть доступна.
Типовая архитектура включает:
Такая структура позволяет отделить UI от сетевой логики и обеспечить предсказуемое поведение при любых условиях подключения.