PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Zustand vs Redux Toolkit: что выбрать в 2024 году

    Zustand vs Redux Toolkit: что выбрать в 2024 году

    Аватар автора Zustand vs Redux Toolkit: что выбрать в 2024 году

    Антон Ларичев

    Иконка календаря26 апреля 2026
    ReactState ManagementZustandRedux ToolkitJavaScriptmiddleИконка уровня middle
    Картинка поста Zustand vs Redux Toolkit: что выбрать в 2024 году

    Введение

    Управление состоянием — одна из ключевых задач в любом React-приложении. Долгое время Redux был стандартом де-факто, но сегодня у него появился серьёзный конкурент — Zustand. Оба инструмента решают одну задачу, но делают это принципиально по-разному.

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

    Архитектура и философия

    Redux Toolkit

    Redux Toolkit (RTK) — это официальный набор инструментов для работы с Redux. Он построен на принципах Flux-архитектуры: единственный глобальный store, иммутабельные обновления через reducers и строгий однонаправленный поток данных.

    RTK значительно упрощает работу с Redux: убирает шаблонный код, встраивает Immer для мутабельных обновлений и предоставляет RTK Query для работы с API.

    Zustand

    Zustand — минималистичная библиотека на основе хуков. Она не навязывает строгую архитектуру: вы создаёте store как обычный JavaScript-объект с состоянием и действиями. Под капотом используется паттерн наблюдателя и контекст React не нужен вовсе.

    Сравнение на практике

    Установка и начало работы

    # Redux Toolkit
    npm install @reduxjs/toolkit react-redux
    
    # Zustand
    npm install zustand
    

    Создание хранилища: Redux Toolkit

    import { createSlice, configureStore, PayloadAction } from '@reduxjs/toolkit';
    
    // Определяем тип состояния
    interface CounterState {
      value: number;
    }
    
    const initialState: CounterState = { value: 0 };
    
    // Создаём slice с редьюсерами и экшенами
    const counterSlice = createSlice({
      name: 'counter',
      initialState,
      reducers: {
        increment: (state) => {
          state.value += 1; // Immer позволяет писать мутации
        },
        decrement: (state) => {
          state.value -= 1;
        },
        setValue: (state, action: PayloadAction<number>) => {
          state.value = action.payload;
        },
      },
    });
    
    export const { increment, decrement, setValue } = counterSlice.actions;
    
    // Настраиваем глобальный store
    export const store = configureStore({
      reducer: {
        counter: counterSlice.reducer,
      },
    });
    
    export type RootState = ReturnType<typeof store.getState>;
    export type AppDispatch = typeof store.dispatch;
    
    // Провайдер оборачивает всё приложение
    import { Provider } from 'react-redux';
    import { store } from './store';
    
    function App() {
      return (
        <Provider store={store}>
          <Counter />
        </Provider>
      );
    }
    
    import { useDispatch, useSelector } from 'react-redux';
    import { increment, decrement } from './counterSlice';
    import { RootState } from './store';
    
    function Counter() {
      const value = useSelector((state: RootState) => state.counter.value);
      const dispatch = useDispatch();
    
      return (
        <div>
          <span>{value}</span>
          <button onClick={() => dispatch(increment())}>+</button>
          <button onClick={() => dispatch(decrement())}>-</button>
        </div>
      );
    }
    

    Создание хранилища: Zustand

    import { create } from 'zustand';
    
    // Типизируем store
    interface CounterStore {
      value: number;
      increment: () => void;
      decrement: () => void;
      setValue: (val: number) => void;
    }
    
    // Создаём store — всё в одном месте
    const useCounterStore = create<CounterStore>((set) => ({
      value: 0,
      increment: () => set((state) => ({ value: state.value + 1 })),
      decrement: () => set((state) => ({ value: state.value - 1 })),
      setValue: (val) => set({ value: val }),
    }));
    
    // Никаких провайдеров не нужно — используем хук напрямую
    function Counter() {
      const { value, increment, decrement } = useCounterStore();
    
      return (
        <div>
          <span>{value}</span>
          <button onClick={increment}>+</button>
          <button onClick={decrement}>-</button>
        </div>
      );
    }
    

    Асинхронные операции

    RTK предоставляет createAsyncThunk для работы с API:

    import { createAsyncThunk } from '@reduxjs/toolkit';
    
    // Асинхронный thunk для загрузки данных пользователя
    export const fetchUser = createAsyncThunk(
      'user/fetchById',
      async (userId: string) => {
        const response = await fetch(`/api/users/${userId}`);
        return response.json();
      }
    );
    

    В Zustand асинхронные действия — просто async-функции:

    interface UserStore {
      user: User | null;
      loading: boolean;
      fetchUser: (id: string) => Promise<void>;
    }
    
    const useUserStore = create<UserStore>((set) => ({
      user: null,
      loading: false,
      // Асинхронное действие — обычная async-функция
      fetchUser: async (id) => {
        set({ loading: true });
        const response = await fetch(`/api/users/${id}`);
        const user = await response.json();
        set({ user, loading: false });
      },
    }));
    

    Производительность и селекторы

    RTK использует reselect для мемоизированных селекторов:

    import { createSelector } from '@reduxjs/toolkit';
    
    // Мемоизированный селектор — пересчитывается только при изменении зависимостей
    const selectFilteredItems = createSelector(
      (state: RootState) => state.items.list,
      (state: RootState) => state.items.filter,
      (list, filter) => list.filter(item => item.category === filter)
    );
    

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

    // Компонент перерендерится только при изменении поля value
    const value = useCounterStore((state) => state.value);
    

    Когда выбирать Redux Toolkit

    • Крупное enterprise-приложение с большой командой
    • Нужны мощные DevTools для отладки и time-travel debugging
    • Сложная бизнес-логика с множеством взаимозависимых состояний
    • Уже используете RTK Query для управления серверным состоянием
    • Требуется строгая архитектура и единые соглашения в команде

    Когда выбирать Zustand

    • Небольшие или средние проекты
    • Нужно быстро стартовать без boilerplate-кода
    • Небольшая команда или соло-разработка
    • Хотите минимальный бандл (Zustand весит около 1 КБ)
    • Нужно локальное состояние нескольких компонентов без глобального store

    Частые ошибки

    Ошибка 1: Подписка на весь store в Zustand

    // Плохо: компонент перерендерится при любом изменении store
    const store = useCounterStore();
    
    // Хорошо: подписываемся только на нужное поле
    const value = useCounterStore((state) => state.value);
    

    Ошибка 2: Мутация состояния в Redux напрямую

    // Плохо: прямая мутация вне Immer-контекста вызовет ошибки
    const badReducer = (state, action) => {
      state.items.push(action.payload); // ошибка вне createSlice
      return state;
    };
    
    // Хорошо: используем createSlice — Immer встроен
    const goodSlice = createSlice({
      name: 'items',
      initialState: { items: [] },
      reducers: {
        addItem: (state, action) => {
          state.items.push(action.payload); // безопасно внутри createSlice
        },
      },
    });
    

    Ошибка 3: Хранить серверные данные в Zustand вместо React Query

    Zustand предназначен для клиентского состояния (UI, фильтры, модалки). Для серверных данных лучше использовать React Query или RTK Query — они берут на себя кэширование, дедупликацию запросов и инвалидацию.

    Ошибка 4: Один огромный store в Zustand

    // Плохо: всё в одном store — сложно поддерживать
    const useAppStore = create(() => ({
      user: null,
      cart: [],
      theme: 'dark',
      notifications: [],
    }));
    
    // Хорошо: разделяем по доменам
    const useUserStore = create(...);
    const useCartStore = create(...);
    const useThemeStore = create(...);
    

    Заключение

    Zustand и Redux Toolkit — отличные инструменты, каждый со своей нишей. Zustand побеждает в простоте, скорости разработки и размере бандла. Redux Toolkit — в структурированности, экосистеме и инструментах отладки.

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

    Иконка глаза1 010

    Постройте личный план изучения TypeScript с нуля - полный курс и паттерны проектирования до уровня Middle — бесплатно!

    TypeScript с нуля - полный курс и паттерны проектирования — часть карты развития Frontend, Backend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    React и Redux Toolkit

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Zustand

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Neovim

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.8
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Тестирование React-компонентов с Jest и React Testing Library
    Иконка аватараАнтон
    Иконка календаря07 октября 2026
    JestReact Testing LibraryТестирование+ 1middleИконка уровня middle

    Тестирование React-компонентов с Jest и React Testing Library

    Jest и React Testing Library: как настроить окружение, писать тесты на поведение пользователя, мокировать запросы и тестировать кастомные хуки.

    Иконка чипа0
    Иконка глаза132
    Иконка комментариев0
    Картинка поста Qwen 3.8 Max для кода: как подключить из России
    Иконка аватараАнтон
    Иконка календаря24 октября 2026
    AI-инструментыapiразработкаjuniorИконка уровня junior

    Qwen 3.8 Max для кода: как подключить из России

    Qwen 3.8 Max — флагманская модель Alibaba с контекстом в 1 млн токенов и ответом до 131 тыс. токенов, которую Alibaba позиционирует прежде всего для программирования. Работать с ней из России проще всего в Qwen Code или OpenCode через ключ AI для кода от PurpleSchool: оплата в рублях, без VPN и без аккаунта Alibaba Cloud. Модель подключается по протоколу OpenAI Responses API — ниже готовые конфиги для обоих клиентов, характеристики модели и частые ошибки.

    Иконка чипа0
    Иконка глаза15
    Иконка комментариев0
    Картинка поста Codex не работает: частые ошибки и решения
    Иконка аватараАнтон
    Иконка календаря23 октября 2026
    AI-инструментыapiразработкаjuniorИконка уровня junior

    Codex не работает: частые ошибки и решения

    Чаще всего Codex не работает по одной из четырёх причин: команда `codex` не находится в системе, Codex пытается войти в аккаунт OpenAI, который из России недоступен, неправильно настроен провайдер в `~/.codex/config.toml` или песочница не даёт командам выйти в сеть. Ниже — ошибки по симптомам: что вы видите, почему это происходит и что исправить. В конце — как включить подробный лог, если ни один пункт не подошёл.

    Иконка чипа0
    Иконка глаза85
    Иконка комментариев0
    Иконка чипа0

    Комментарии

    1
    Иконка аватара
    Andrei Miagkov

    05.05.2026

    Дата похоже старая в заголовке)