Перейти к содержанию
Innovialabs

Управление состоянием в React: Context, Redux или Zustand

Практика3 мин

Коротко

Сначала отделите серверные данные (их отдайте TanStack Query) от клиентского состояния; для редких глобальных значений хватит Context, для частых — Zustand, для большой команды со строгими правилами — Redux Toolkit.

Короткий ответ

Большинство проблем с состоянием в React возникает из-за того, что разные виды состояния хранят одним способом. Правильный выбор начинается не с библиотеки, а с вопроса: что это за данные?

  • Серверные данные (списки, профили, заказы) — TanStack Query или аналог.
  • Локальное состояние (открыт ли модал, значение поля) — useState в компоненте.
  • Глобальное клиентское состояние (тема, корзина, авторизованный пользователь) — Context, Zustand или Redux.

Три вида состояния

Локальное. Нужно одному компоненту или небольшому поддереву. Храните его как можно ближе к месту использования. Поднимайте выше только когда данные реально нужны соседям.

Глобальное клиентское. Нужно многим частям приложения и существует только в браузере: тема, язык, содержимое корзины до оформления, состояние сложного мастера.

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

Сравнение инструментов

ИнструментДля чего подходитМинусы
ContextРедко меняющиеся значения: тема, язык, текущий пользовательПри изменении значения перерисовываются все потребители
ZustandГлобальное состояние с частыми обновлениями, минимум кодаМеньше встроенных соглашений, структуру задаёт команда
Redux ToolkitБольшие приложения, сложная бизнес-логика, много разработчиковБольше шаблонного кода и понятий для изучения
TanStack QueryСерверные данные: загрузка, кеш, мутацииНе предназначен для чисто клиентского состояния

Context: встроенный, но не менеджер состояния

Context — это механизм передачи значения вниз по дереву без пропсов. Сам по себе он не оптимизирует обновления: если значение провайдера меняется, перерисовываются все компоненты, которые его читают.

Практические правила:

  • Разделяйте контексты по смыслу: ThemeContext отдельно от CartContext.
  • Мемоизируйте значение провайдера, если передаёте объект.
  • Не кладите в Context то, что меняется при каждом вводе символа.

Zustand: простое глобальное хранилище

import { create } from 'zustand';

export const useCart = create((set) => ({
  items: [],
  add: (item) => set((s) => ({ items: [...s.items, item] })),
  clear: () => set({ items: [] }),
}));

// В компоненте подписываемся только на нужную часть
const count = useCart((s) => s.items.length);

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

Redux Toolkit: когда нужна строгость

Redux Toolkit — современный способ писать на Redux. Он даёт предсказуемый однонаправленный поток данных, удобные DevTools с историей действий и устоявшиеся паттерны. Это ценно, когда над кодом работает много людей и бизнес-логика сложная. В комплекте есть RTK Query для серверных данных.

TanStack Query: серверное состояние отдельно

const { data, isPending, error } = useQuery({
  queryKey: ['orders', userId],
  queryFn: () => fetchOrders(userId),
});

Библиотека сама кеширует ответы, дедуплицирует запросы и обновляет данные при возвращении на вкладку. После переноса серверных данных сюда глобального клиентского состояния обычно остаётся совсем немного.

Как выбрать по размеру приложения

  1. Лендинг или небольшое приложение: useState + Context для темы и языка.
  2. Среднее приложение с API: TanStack Query для данных + Zustand или Context для остального.
  3. Крупный продукт, большая команда: TanStack Query или RTK Query + Redux Toolkit для сложной клиентской логики.

Частые ошибки: хранить всё глобально «на всякий случай», дублировать серверные данные в нескольких хранилищах, выбирать Redux для приложения из пяти экранов.

Частые вопросы

Да, это распространённая связка: TanStack Query отвечает за данные с сервера, Zustand — за клиентское состояние вроде фильтров, корзины или открытых панелей.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.