Состояние — это сердце любого приложения. Если оно ведёт себя непредсказуемо, даже самый красивый интерфейс будет раздражать пользователей. В этой статье разберём, как навести порядок в данных и не сойти с ума от багов.

Digital-студия WNDER

Что такое состояние и почему с ним столько проблем

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

Вспомните ситуацию: вы обновили имя пользователя в одном месте, а в шапке оно осталось старым. Или корзина показывает одно количество товаров, а бейдж в меню — другое. Это классические симптомы «разъехавшегося» состояния.

Три кита управления состоянием

Чтобы не утонуть в хаосе, запомните три принципа:

  • Единый источник правды. Для каждого кусочка данных должен быть один «главный» объект или хранилище.
  • Однонаправленный поток. Данные идут в одну сторону: от хранилища к компонентам, а изменения — только через специальные действия.
  • Иммутабельность. Не меняйте объекты напрямую, создавайте новые. Так проще отслеживать изменения.
Правило: Если два компонента используют одни и те же данные, поднимите состояние до их общего родителя. Это избавит от синхронизации вручную.

Локальное состояние vs глобальное: когда что выбирать

Не всё состояние нужно тащить в глобальное хранилище. Локальное (внутри компонента) — проще и быстрее. Глобальное — нужно, когда данные разделяются между удалёнными частями приложения.

Критерий Локальное состояние Глобальное состояние
Где используется Внутри одного компонента или его детей В разных, не связанных напрямую компонентах
Пример Открыт ли выпадающий список Данные авторизованного пользователя
Сложность Низкая Средняя или высокая
Инструменты useState, useReducer Redux, MobX, Context, Zustand

Популярные инструменты и их место

Выбор инструмента — как выбор молотка: для гвоздя не нужен отбойный молоток.

  • React Context — хорош для передачи данных, которые редко меняются (тема, язык). Но если состояние часто обновляется, контекст может вызвать лишние ререндеры.
  • Redux — мощный, предсказуемый, но требует много шаблонного кода. Идеален для больших команд и сложной логики.
  • MobX — меньше кода, реактивный. Подходит, если вы любите ООП и не хотите писать много экшенов.
  • Zustand — лёгкий, простой, без лишнего оверхеда. Хорош для средних проектов.
Лайфхак: Начните с локального состояния и Context. Если почувствуете, что логика усложняется — переходите на специализированную библиотеку. Не тащите Redux в проект из трёх экранов.

Практические примеры: как не наступить на грабли

Рассмотрим типичные ошибки и их решения.

Пример 1: Обновление вложенного объекта

Часто разработчики мутируют состояние напрямую, что приводит к неожиданностям.

// Плохо: мутация
const [user, setUser] = useState({ name: 'Alice', age: 25 });
function updateAge() {
  user.age = 26; // напрямую меняем объект
  setUser(user); // React может не заметить изменений
}

// Хорошо: иммутабельно
function updateAge() {
  setUser(prev => ({ ...prev, age: 26 }));
}

Пример 2: Слишком много глобального состояния

Если хранить в Redux всё подряд, приложение станет тяжёлым.

// Плохо: в глобальном хранилище лежит флаг открытия модалки
const initialState = {
  isModalOpen: false,
  // ... другие глобальные данные
};

// Хорошо: этот флаг — локальный для компонента
function Modal() {
  const [isOpen, setIsOpen] = useState(false);
  // ...
}

Пример 3: Использование Context для часто меняющихся данных

Context вызывает ререндер всех потребителей при изменении значения.

// Плохо: таймер в контексте
const TimerContext = createContext();
function TimerProvider({ children }) {
  const [time, setTime] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setTime(t => t + 1), 1000);
    return () => clearInterval(id);
  }, []);
  return {children};
}
// Все компоненты, использующие контекст, будут перерисовываться каждую секунду.

// Лучше: вынести таймер в отдельный компонент или использовать библиотеку с селекторами.

Заключение

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

Начните с малого, рефакторите по мере роста, и ваше приложение скажет вам спасибо.

Студия WNDER