Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про JavaScript: immutability, state mutation, React, Redux, side effects

Почему нельзя мутировать состояние напрямую?

Вопрос проверяет понимание принципов иммутабельности в управлении состоянием, что критично для корректной работы реактивных систем и предотвращения трудноуловимых багов.

Короткий ответ

Прямая мутация состояния нарушает принцип иммутабельности, который является основой предсказуемости в современных UI-фреймворках. Когда объект мутируется напрямую, ссылка на него остаётся прежней, и система не может обнаружить, что состояние изменилось. Это приводит к тому, что компоненты не перерисовываются, кэши не инвалидируются, а история изменений теряется. Вместо этого нужно создавать новые объекты или массивы, например, используя оператор spread или методы вроде map и filter.

Длинный ответ

Прямая мутация состояния — это изменение значений внутри существующего объекта или массива без создания новой ссылки. В контексте React, Redux и многих других систем управления состоянием это считается антипаттерном, потому что нарушает принцип иммутабельности (неизменяемости данных).

Почему это проблема?

  • Нарушение реактивности: React и аналогичные библиотеки полагаются на сравнение ссылок (shallow comparison) для определения, изменилось ли состояние. Если вы мутируете объект на месте, его ссылка остаётся той же, и React «не видит» изменений, что приводит к пропущенным ререндерам.
  • Сложность отладки: Когда состояние мутируется в разных частях приложения, становится крайне трудно отследить, где и когда произошло изменение, особенно в асинхронном коде. Это усложняет воспроизведение багов.
  • Нарушение работы PureComponent и React.memo: Эти оптимизации зависят от поверхностного сравнения пропсов. Если вы передаёте мутированный объект, сравнение не сработает, и компонент может не обновиться, когда нужно, или обновиться, когда не нужно.
  • Проблемы с историей и откатом: В таких библиотеках, как Redux, devtools и middleware (например, redux-thunk) полагаются на то, что каждое состояние — это новый неизменяемый снапшот. Мутация ломает возможность "путешествия во времени" и логирования.

Практический пример

Рассмотрим типичную ошибку при обновлении массива в React-компоненте:

// ❌ ПЛОХО: прямая мутация
const [todos, setTodos] = useState([{ id: 1, text: 'Learn React' }]);
const addTodoBad = (newTodo) => {
  todos.push(newTodo); // Мутация существующего массива!
  setTodos(todos); // Ссылка не изменилась, React может проигнорировать обновление
};

// ✅ ХОРОШО: создание нового массива
const addTodoGood = (newTodo) => {
  setTodos([...todos, newTodo]); // Новый массив, новая ссылка
};

// Пример с объектом
const [user, setUser] = useState({ name: 'Alice', age: 30 });
// ❌ user.age = 31;
// ✅ setUser({ ...user, age: 31 });

Где это применяется?

Принцип неизменяемости состояния является краеугольным камнем не только в React и Redux, но и в библиотеках для глобального состояния (MobX, хотя он использует наблюдаемые объекты, также рекомендует аккуратные мутации), в функциональном программировании, и даже в системах типа Immer, которые предоставляют API для записи мутабельного кода, но под капотом генерируют новые неизменяемые структуры.

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

Уровень

  • Рейтинг:

    4

  • Сложность:

    3

Навыки

  • JavaScript

    JavaScript

  • React

    React

Ключевые слова

#immutability

#state mutation

#React

#Redux

#side effects

Подпишись на React Developer в телеграм