Почему в React нельзя изменять состояние напрямую?
- Почему компонент не перерисовался после push в массив состояния?
React узнаёт об изменении, сравнивая ссылки (Object.is). Мутация (items.push(x), user.name = ...) оставляет ссылку прежней — перерисовки не будет, а memo и useEffect не увидят изменений. Состояние обновляют новым объектом: spread, map, filter, toSorted.
- Добавить: setItems([...items, x]); удалить: filter; изменить: map
- Вложенные объекты копируют по всему пути до изменения
- Immer (встроен в Redux Toolkit) позволяет писать «мутирующий» код безопасно
А ещё Мутация ещё и ломает предыдущие значения, которые могли сохраниться в замыканиях
Подробно
Механика. setState(next) сравнивает next с текущим значением через Object.is. Совпали — React может пропустить рендер. Мутация меняет содержимое, но не ссылку.
Почему это хорошо, а не ограничение: сравнение ссылок — O(1), на нём построены React.memo, useMemo, зависимости эффектов. Неизменяемые данные дают историю (отмена действия), простую отладку и безопасность при параллельном рендеринге.
Глубокие структуры — копировать путь до изменённого поля или нормализовать данные (хранить сущности плоско по id).
Пример
// плохо
items.push(newItem);
setItems(items); // та же ссылка — React пропустит
// хорошо
setItems(prev => [...prev, newItem]);
setItems(prev => prev.map(i => i.id === id ? { ...i, done: true } : i));
setUser(prev => ({ ...prev, address: { ...prev.address, city } }));Что хотят услышать
- Сравнение по ссылке.
- Правильные способы обновления массивов и объектов.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗items.push(x) — правильный способ добавить элемент в состояние
- ✗React глубоко сравнивает объекты состояния, поэтому мутация тоже вызовет перерисовку
- ✗Мутация состояния ускоряет перерисовку
- ✓React сравнивает ссылки: после мутации ссылка прежняя, перерисовки не будет; нужен новый объект
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.