> Нужно ли мутировать массив товаров или создавать его копию для обновления состояния в React? (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: РСХБ

Стек: React

> Пример ответа

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

В React мутировать массив товаров для обновления состояния нельзя - это нарушает принцип иммутабельности и может привести к багам, так как React не обнаружит изменения. Нужно создавать новую копию массива (через spread, concat, map, filter, slice или Immer) и передавать её в setState. Это гарантирует корректное обнаружение изменений и предсказуемое поведение компонентов.

Подробное объяснение

React использует поверхностное сравнение (shallow comparison) для определения, изменилось ли состояние. Если вы мутируете массив напрямую (например, items.push(newItem)), ссылка на объект остаётся той же, и React не перерендерит компонент, даже если содержимое массива изменилось. Это приводит к рассинхронизации UI и данных.

Иммутабельность - ключевой принцип в React. Она обеспечивает:

  • Предсказуемость: состояние не меняется неожиданно в других частях приложения
  • Возможность отладки: можно отследить каждое изменение через devtools
  • Оптимизацию: PureComponent и React.memo работают корректно
  • Безопасность: отсутствие side effects при передаче пропсов

Для обновления массива товаров нужно создавать новый массив с помощью методов, возвращающих новую ссылку: map, filter, concat, slice, spread-оператор ([...items]). Для вложенных объектов внутри массива также требуется копирование на каждом уровне.

На практике

В реальных проектах с простыми массивами используют spread или методы массива. Для сложных вложенных структур или частых обновлений применяют Immer - библиотеку, которая позволяет писать мутабельный код, но под капотом создаёт иммутабельные копии.

Пример типичного сценария: добавление товара в корзину. Мутация cart.push(item) не сработает - нужно setCart([...cart, item]). Удаление товара - через filter, обновление количества - через map с копированием изменяемого объекта.

Пример кода

JAVASCRIPT
// ❌ Неправильно: мутация массива
const handleAdd = (newItem) => {
items.push(newItem); // мутация
setItems(items); // React не обнаружит изменение
};
// ✅ Правильно: создание копии
const handleAdd = (newItem) => {
setItems(prevItems => [...prevItems, newItem]);
};
// ✅ Удаление товара
const handleRemove = (id) => {
setItems(prevItems => prevItems.filter(item => item.id !== id));
};
// ✅ Обновление поля в товаре
const handleUpdate = (id, newPrice) => {
setItems(prevItems =>
prevItems.map(item =>
item.id === id ? { ...item, price: newPrice } : item
)
);
};
// ✅ С Immer (для сложных структур)
import { produce } from 'immer';
const handleUpdate = (id, newPrice) => {
setItems(produce(draft => {
const item = draft.find(i => i.id === id);
if (item) item.price = newPrice;
}));
};

Как отвечать на собеседовании

Начни с чёткого ответа: мутировать нельзя, нужно создавать копию. Объясни причину - механизм обнаружения изменений в React. Приведи конкретные примеры методов для разных операций (добавление, удаление, обновление). Упомяни Immer как инструмент для упрощения работы с глубокими структурами. Покажи понимание trade-off: производительность при больших массивах (копирование может быть затратным) и альтернативы (например, useReducer с Immer). Заверши рекомендацией: для простых случаев - spread и map, для сложных - Immer.

Что проверяет интервьюер

  • Понимание принципа иммутабельности в React и его связи с рендерингом
  • Знание механизма обнаружения изменений (shallow comparison)
  • Умение работать с массивами и объектами иммутабельно
  • Осведомлённость о библиотеках (Immer) и их trade-off
  • Способность объяснить, почему мутация - это баг, а не просто плохая практика

Типичные ошибки

  • Использование push, splice, sort напрямую на массиве состояния
  • Забывание копировать вложенные объекты при обновлении (только поверхностное копирование)
  • Применение setItems([...items]) без учёта предыдущего состояния в замыкании (нужно использовать функциональную форму setItems(prev => ...))
  • Утверждение, что мутация работает, если вызвать forceUpdate - это хак, а не решение
  • Игнорирование производительности: копирование массива из 10 000 элементов на каждый клик - плохая идея, лучше использовать библиотеки или структуры данных с персистентностью

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью