Виды состояния и как выбрать
Локальное, серверное, URL, форма, глобальное — у каждого свой инструмент.
Обновлено
Что такое стейт-менеджмент
Стейт-менеджмент = решения о том, где хранить меняющиеся данные приложения, кто может их читать и как они обновляются. В маленьком приложении хватает useState. Когда нескольким далёким друг от друга компонентам нужны одни и те же данные, возникает вопрос: куда их положить?
Главная идея урока: «состояние» не одно. Есть несколько видов, и у каждого свой инструмент. Классическая ошибка — запихнуть всё в один глобальный стор.
Виды состояния
| Вид | Примеры | Подходящий инструмент |
|---|---|---|
| локальное UI | открытая модалка, активная вкладка, поле ввода | useState, useReducer |
| серверное | пользователи, товары, заказы | Server Components, TanStack Query, RTK Query |
| URL | фильтры, страница, сортировка, поиск | searchParams, useSearchParams |
| форма | значения, ошибки, pending | <form> + useActionState, React Hook Form |
| глобальное клиентское | корзина в SPA, настройки, вошедший пользователь в UI | Context, Zustand, Redux Toolkit |
| постоянное локальное | тема, черновики | localStorage + стор |
Как выбрать — вопросы по порядку
Задавайте вопросы по порядку и остановитесь на первом «да»:
- Приходит с сервера? → серверное состояние (Server Components, TanStack Query, RTK Query).
- Нужно делиться ссылкой? → URL.
- Использует один компонент? →
useState. - Используют несколько близких компонентов? → поднимите состояние в общего родителя.
- Используют многие компоненты, но меняется редко? → Context.
- Глобальное и меняется часто? → Zustand или Redux Toolkit.
Context — что это и чем он не является
Context передаёт значение вниз по дереву без props на каждом уровне. Это не стейт-менеджер — только механизм передачи.
| Хорош для | Проблемен для |
|---|---|
| темы, языка, вошедшего пользователя — редко меняющихся значений | часто меняющихся данных: каждое изменение перерисовывает всех потребителей |
| dependency injection (API-клиент, конфиг) | большого состояния с множеством независимых полей |
Библиотеки глобального состояния — сравнение
| Context + useReducer | Zustand | Redux Toolkit | Jotai | |
|---|---|---|---|---|
| Модель | значение в дереве | один стор, хук с селектором | один стор, слайсы, действия | маленькие атомы |
| Бойлерплейт | мало | очень мало | средне | мало |
| Перерисовки | все потребители | только выбранное | только выбранное | только используемые атомы |
| DevTools, time-travel | нет | по желанию | отличные | по желанию |
| Серверное состояние в комплекте | нет | нет | да — RTK Query | нет |
| Когда | редкие значения | по умолчанию для большинства приложений | большие команды, сложная логика, существующий код на Redux | дробное, производное состояние |
Что изменилось с Next.js App Router
С Server Components многое из того, что жило в Redux (списки товаров, профиль пользователя), читается прямо на сервере. Глобальное клиентское состояние становится гораздо меньше — часто это только UI (открытый сайдбар, корзина, настройки). Поэтому Zustand и даже Context часто достаточно.
Коротко
- Видов состояния несколько; у каждого свой инструмент.
- Серверное состояние → серверный кэш, а не глобальный стор; фильтры → URL.
- Context = передача редких значений; Zustand по умолчанию для глобального; Redux Toolkit для больших приложений.