Zustand vs Redux Toolkit vs Jotai в 2026
За последние пять лет я работала с тремя разными подходами к управлению состоянием в React: Redux Toolkit, Zustand и Jotai. На разных проектах — разные, и каждый раз выбор был осмысленным, а не «просто потому что». В 2026 году картина устаканилась: каждая библиотека закрепилась за своей нишей, и пайплайн выбора стал понятнее.
В двух предложениях о каждой
Redux Toolkit — большой централизованный стор с строгими правилами. Лучшая поддержка инструментами (DevTools, time-travel, middleware), отличная документация, отработанные паттерны для команды.
Zustand — легковесный стор без boilerplate. Минимум API, максимум контроля, прекрасно интегрируется с TypeScript. Любой junior разбирается за полчаса.
Jotai — атомарное состояние. Каждое значение — отдельный атом, компоненты подписываются точечно. Изысканная модель для UI с большим количеством мелких независимых стейтов.
Когда я беру Redux Toolkit
Большие проекты, где над кодом работает много команд. RTK даёт каркас, который не разваливается, когда у тебя в проекте сорок разработчиков. Все знают, что такое slice, что такое reducer, как работает createAsyncThunk. На ревью не нужно пересказывать архитектуру — она в библиотеке.
RTK Query особенно хорош, когда ты хочешь типизированный API-клиент с автоматическим кешированием. По сравнению с обычным createApi в каноническом Redux он сильно ускоряет работу: эндпоинты описываются один раз, хуки генерируются автоматически.
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
tagTypes: ['Post'],
endpoints: (b) => ({
getPosts: b.query<Post[], void>({
query: () => '/posts',
providesTags: ['Post'],
}),
addPost: b.mutation<Post, Partial<Post>>({
query: (body) => ({ url: '/posts', method: 'POST', body }),
invalidatesTags: ['Post'],
}),
}),
});
export const { useGetPostsQuery, useAddPostMutation } = api;В компонентах хуки выглядят как обычные React-хуки, но за ними — кеш, ревалидации и работа с гонками.
Минусы Redux Toolkit
Boilerplate. Даже с RTK на простой счётчик уходит десяток строк. На лендинг с минимальной интерактивностью ставить целый Redux — оверкилл.
Серверные компоненты в Next.js. Redux нативно живёт на клиенте, и в RSC его не используешь. Можно держать кеш данных на сервере отдельно (через cache и revalidateTag), а Redux оставить только для клиентского state. Эта граница в архитектуре требует внимания.
Когда я беру Zustand
Средний и маленький проект, в котором нужен общий state, но не хочется тащить тяжёлую инфраструктуру. Zustand — мой дефолт уже два года.
import { create } from 'zustand';
type CartState = {
items: { id: string; qty: number }[];
add: (id: string) => void;
clear: () => void;
};
export const useCart = create<CartState>((set) => ({
items: [],
add: (id) =>
set((s) => {
const existing = s.items.find((i) => i.id === id);
if (existing) {
return { items: s.items.map((i) => (i.id === id ? { ...i, qty: i.qty + 1 } : i)) };
}
return { items: [...s.items, { id, qty: 1 }] };
}),
clear: () => set({ items: [] }),
}));В компоненте:
const items = useCart((s) => s.items);
const add = useCart((s) => s.add);Это всё. Подписка точечная (по селектору), DevTools работают через middleware, persist в localStorage — одна строчка.
Zustand хорошо подходит для UI-state: открыта ли модалка, какая активная вкладка, какие фильтры применены. Я в одном проекте держу штук десять отдельных сторов: для аутентификации, для UI-настроек, для корзины, для черновиков. Это не перегружает архитектуру и легко читается.
Когда я беру Jotai
Когда состояние очень атомарное и не складывается в централизованный слайс. Самый частый кейс — сложные формы с большим количеством зависимых полей.
import { atom, useAtom } from 'jotai';
const nameAtom = atom('');
const emailAtom = atom('');
const isValidAtom = atom((get) => {
const name = get(nameAtom);
const email = get(emailAtom);
return name.length > 1 && email.includes('@');
});
function Form() {
const [name, setName] = useAtom(nameAtom);
const [email, setEmail] = useAtom(emailAtom);
const [valid] = useAtom(isValidAtom);
// ...
}Производное значение isValidAtom само пересчитается, когда изменится один из источников. И каждый компонент подписан только на свои атомы — никаких лишних перерисовок.
Jotai сильна в дизайн-системах с большим количеством взаимосвязанных контролов. На дашбордах со сложными фильтрами, на конструкторах форм она экономит много кода. На обычной CRUD-административке выглядит избыточно.
Сравнение по 7 критериям
В сухой таблице оно бы выглядело так, но я обещала не делать таблиц — пройдусь списком.
- Boilerplate. Меньше всех — Zustand. Чуть больше — Jotai (но без структуры). Больше всех — RTK.
- DevTools. Лучше всех — RTK. Хорошо — Zustand (через middleware). Слабее — Jotai (есть, но кустарные).
- TypeScript. Все три отлично типизированы. Zustand чуть проще пишется, RTK даёт строгие сигнатуры из коробки, Jotai требует немного танцев со
WritableAtom<V, A, R>. - SSR / Next App Router. Все три работают, но требуют аккуратности с гидрацией. Zustand часто использую с инициализацией через провайдер. RTK — официальный гайд по SSR. Jotai — провайдер с
store. - Кеш данных с сервера. RTK Query — встроен. Для Zustand и Jotai я беру TanStack Query.
- Кривая обучения. Меньше всего — Zustand, день. Jotai — два-три дня, чтобы привыкнуть к атомам. RTK — неделя на освоение всех концептов.
- Подходит junior-команде. Zustand. RTK слишком формальный, Jotai требует ментальной перестройки.
Что я не использую
Recoil. На бумаге похож на Jotai, но в 2026 году развивается медленнее, и почти всё, что есть в Recoil, есть в Jotai в более чистом виде.
MobX. Прекрасная библиотека, но сильно вышла из моды, и команда сейчас редко её знает. Я бы не закладывала её в новый проект, если только не работаю в окружении, где это уже стандарт.
Redux без Toolkit. Бесполезный самобичевание. RTK — это «правильный Redux», и любой свежий проект на классическом Redux — это технический долг с первого дня.
Гибридные подходы
На большом проекте можно держать всё одновременно. У меня сейчас:
- RTK Query — для всех серверных данных (CRUD-эндпоинты).
- Zustand — для UI-настроек и корзины.
- Jotai — для одного конструктора форм с двадцатью полями.
Звучит как «зоопарк», но на практике работает. Каждая библиотека делает свою задачу, и команда быстро привыкает: «серверные данные — RTK, UI — Zustand, форма — Jotai». Главное не плодить дубликаты: одно и то же состояние не должно жить в двух местах.
Что копать дальше
Если ты впервые выбираешь, бери Zustand на первый проект. Он самый простой и не накладывает ограничений на архитектуру. Через год-другой, когда команда вырастет, перейти на RTK будет несложно — слайсы можно постепенно мигрировать. Jotai разумно начать использовать, когда ты увидишь конкретный кейс, который в Zustand плохо ложится.