← Назад к вопросам

Какие cтэйт-менеджеры использовал кроме Redux?

2.0 Middle🔥 211 комментариев
#State Management

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Моё знакомство с альтернативными стэйт-менеджерами

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

1. MobX

MobX стал для меня первым серьёзным опытом с альтернативным подходом, основанным на реактивном программировании и наблюдаемых объектах (observables). Я использовал его в двух крупных SPA-приложениях.

  • Ключевые концепции: Вместо иммутабельного состояния и чистых редьюсеров, как в Redux, MobX позволяет работать с изменяемыми данными, используя декораторы (или функции) @observable, @computed и @action.
  • Преимущества, которые я оценил: Значительно меньше шаблонного кода (boilerplate) по сравнению с классическим Redux. Состояние обновляется "магически" — компоненты автоматически реагируют на изменения тех наблюдаемых полей, которые они используют. Это делает код более декларативным и простым для понимания.
  • Пример использования:
import { makeObservable, observable, action, computed } from "mobx";
import { observer } from "mobx-react-lite";

class TodoStore {
  todos = [];

  constructor() {
    makeObservable(this, {
      todos: observable,
      addTodo: action,
      completedCount: computed,
    });
  }

  addTodo(text) {
    this.todos.push({ id: Date.now(), text, completed: false });
  }

  get completedCount() {
    return this.todos.filter(t => t.completed).length;
  }
}

const store = new TodoStore();

// Компонент React, обёрнутый в observer, будет перерендериваться только при изменении используемых им observable полей.
const TodoList = observer(({ store }) => (
  <div>
    <span>Completed: {store.completedCount}</span>
    {store.todos.map(todo => <div key={todo.id}>{todo.text}</div>)}
  </div>
));

2. Zustand

Zustand — это минималистичная, но мощная библиотека, которую я выбрал для нескольких последних проектов. Она удачно сочетает простоту и гибкость.

  • Ключевые концепции: Создание хранилища (store) — это просто вызов функции create. Состояние — это изменяемый объект, но обновления производятся через иммутабельные функции (похожие на setState в React). Библиотека очень легковесна и не требует оборачивания приложения в провайдер (Provider).
  • Преимущества, которые я оценил: Практически отсутствует boilerplate. Отличная интеграция с React. Встроенная поддержка селекторов и middleware (например, для дебаггинга или persistence). Работать с ним интуитивно понятно, особенно если есть опыт с React-стейтом.
  • Пример использования:
import create from 'zustand';
import { persist } from 'zustand/middleware';

const useBearStore = create(persist(
  (set, get) => ({
    bears:监测0,
    increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
    removeAllBears: () => set({ bears: 0 }),
    // Легко создавать производные состояния (аналогично computed в MobX)
    get bearDescription() {
      const count = get().bears;
      return `There are ${count} bears in the store`;
    }
  }),
  {
    name: 'bear-storage', // имя для localStorage
  }
));

// Использование в компоненте
function BearCounter() {
  const bears = useBearStore(state => state.bears);
  const increase = useBearStore(state => state.increasePopulation);
  const description = useBearStore(state => state.bearDescription);

  return (
    <>
      <h1>{bears} bears around here</h1>
      <p>{description}</p>
      <button onClick={increase}>Add one</button>
    </>
  );
}

3. Context API + useReducer

Для небольших и средних приложений я часто использовал встроенное решение React — комбинацию Context API и хука useReducer. Это не отдельная библиотека, но полноценный стэйт-менеджер.

  • Ключевые концепции: useReducer предоставляет Redux-MQ схему (стейт, действия, редьюсер) в пределах компонента или контекста. Context позволяет передать это состояние вглубь дерева компонентов без пропс-дриллинга.
  • Преимущества, которые я оценил: Не требует внешних зависимостей. Отлично подходит для логически изолированных частей состояния (например, тема UI, аутентификация, модальные окна). Позволяет избежать излишней сложности, когда глобальное хранилище (как Redux) было бы overkill.
  • Пример использования:
import React, { createContext, useReducer, useContext, useMemo } from 'react';

const AuthContext = createContext();

function authReducer(state, action) {
  switch (action.type) {
    case 'LOGIN':
      return { user: action.payload, isAuthenticated: true };
    case 'LOGOUT':
      return { user: null, isAuthenticated: false };
    default:
      return state;
  }
}

function AuthProvider({ children }) {
  const [state, dispatch] = useReducer(authReducer, { user: null, isAuthenticated: false });
  // Мемоизация значения контекста для оптимизации
  const value = useMemo(() => ({ state, dispatch }), [state]);

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

// В компоненте
function LoginButton() {
  const { state, dispatch } = useAuth();
  return (
    <button onClick={() => dispatch({ type: 'LOGIN', payload: { name: 'John' } })}>
      Log in as John
    </button>
  );
}

4. Recoil (экспериментальный опыт)

Я также изучал Recoil от Facebook (ныне Meta) для одного внутреннего экспериментального проекта. Его ключевые концепции — atoms (мельчайшие части состояния) и selectors (производные состояния). Он предлагает очень React-(хороший) способ управления состоянием, но на момент моего использования был ещё недостаточно зрелым, и его долгосрочная поддержка вызывала вопросы. Поэтому для продакшена я пока предпочитал более стабильные варианты, такие как Zustand или MobX.

Критерии выбора стэйт-менеджера в моей практике

  • Масштаб проекта: Для небольших — Context + useReducer, для средних и крупных — Zustand или MobX.
  • Сложность состояния: Если много производных данных (computed) — MobX. Если нужна простая централизованная модель — Zustand.
  • Производительность: Все современные библиотеки (Zustand, MobX, Recoil) предлагают тонко-настроенную подписку на изменения, что минимизирует перерендеры. Для Redux это требовало ручной оптимизации с React.memo и селекторами.
  • Предпочтения команды: Простота освоения (Zustand часто выигрывает) и согласованность с архитектурными принципами проекта.

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