webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
React · Урок 7 из 7

Серверное состояние и TanStack Query

Почему данные с сервера — это не useState, query keys, staleTime и инвалидация.

Обновлено

Что такое серверное состояние

Серверное состояние (server state) = данные, которые живут на сервере (в базе, в API), а в браузере у вас лишь копия: пользователи, товары, заказы, комментарии. Противоположность — клиентское состояние: данные, которые есть только в интерфейсе, — открытая модалка, текст в поле, тема.

Разница не академическая — у них совершенно разные проблемы:

Клиентское состояние Серверное состояние
Примеры тема, открытая модалка, шаг мастера пользователи, товары, заказы
Владелец вы (интерфейс) сервер — у вас копия
Синхронное да нет — приходит по сети
Может устареть нет в любой момент (другой пользователь изменил)
Проблемы где хранить загрузка, ошибки, кэш, дедупликация, повторные запросы, инвалидация, пагинация
Инструменты useState, URL, Zustand Server Components, TanStack Query, SWR

Классическая ошибка — серверные данные в useState + useEffect. В итоге вы заново (и плохо) реализуете кэш, загрузку, повторы, дедупликацию.

Вариант 1: Server Components (Next.js)

Данные получают на сервере и сразу рендерят HTML. Нет состояния загрузки на клиенте, нет кэша, который нужно синхронизировать в браузере.

export default async function Page() {
  const posts = await getPosts()        // кэшируется через 'use cache' + cacheTag('posts')
  return <PostList posts={posts} />
}

Мутация → Server Action → updateTag('posts') → страница перерисовывается со свежими данными.

Вариант 2: TanStack Query (на клиенте)

Библиотека, которая управляет серверным состоянием в браузере: кэш, повторные запросы, дедупликация, повторы при ошибке, пагинация, мутации.

const { data, isPending, error } = useQuery({
  queryKey: ['posts', { page }],                       // идентичность данных в кэше
  queryFn: () => api(`/api/posts?page=${page}`),
  staleTime: 60_000,                                   // свежие 1 мин → без повторного запроса
})

const queryClient = useQueryClient()
const createPost = useMutation({
  mutationFn: (post: NewPost) => api('/api/posts', { method: 'POST', body: JSON.stringify(post) }),
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
})

Ключевые понятия

Понятие Что означает
queryKey массив, идентифицирующий данные; всё, что влияет на результат, входит в ключ (page, фильтры)
staleTime сколько данные считаются «свежими»; по умолчанию 0 = всегда устаревшие
gcTime сколько данные остаются в кэше, когда их никто не использует (по умолчанию 5 мин)
invalidateQueries помечает устаревшими → повторный запрос для того, что на экране; совпадение по префиксу
дедупликация 3 компонента запрашивают ['user', 1] → один запрос
автоматический повторный запрос при фокусе окна, при переподключении, при монтировании (если устарели)

Оптимистичное обновление

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

Где Как
React 19 / Server Actions useOptimistic
TanStack Query onMutate (обновляете кэш) + onError (откат)

Как выбрать

Ситуация Выбор
страницы Next, которые показывают данные (блог, каталог, профиль) Server Components
мутации из форм в Next Server Actions + updateTag
очень интерактивный интерфейс с серверными данными: дашборд, бесконечная прокрутка, polling, живые фильтры TanStack Query (можно делать prefetch на сервере)
SPA без собственного сервера TanStack Query
чисто интерфейсное состояние useState / URL / Zustand

Коротко

  • Серверное состояние = локальная копия данных с сервера; может устареть в любой момент.
  • Не кладите его в useState + useEffect.
  • Next: Server Components + Server Actions; на клиенте: TanStack Query с queryKey, staleTime, инвалидацией.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.