> Является ли изменение пропсов триггером ререндеринга в React (React)

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

Компании: Kodix

Стек: React

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

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

Да, изменение пропсов является триггером ререндеринга в React. Когда родительский компонент передаёт дочернему новые пропсы (по ссылке или значению), React сравнивает предыдущие и новые пропсы с помощью shallow comparison. Если обнаружено различие, дочерний компонент ререндерится. Это поведение можно контролировать с помощью React.memo или shouldComponentUpdate.

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

В React ререндеринг компонента происходит при изменении state или пропсов. Механизм выглядит так:

  1. Родительский компонент ререндерится (из-за изменения своего state или пропсов)
  2. React создаёт новое дерево элементов для дочернего компонента с новыми пропсами
  3. React сравнивает предыдущие пропсы с новыми через Object.is (shallow comparison)
  4. Если хотя бы одно значение изменилось - компонент ререндерится

Важно понимать: даже если пропсы не изменились по значению, но родитель ререндерится, дочерний компонент всё равно получит новые ссылки на объекты/функции, что приведёт к ререндеру. Это называется "unnecessary re-render" и решается через React.memo (для функциональных компонентов) или shouldComponentUpdate (для классовых).

React.memo выполняет поверхностное сравнение пропсов и пропускает ререндер, если пропсы не изменились. Однако при передаче inline-функций или объектов сравнение всегда будет false, поэтому нужны useCallback и useMemo.

На практике

  • Изменение примитивных пропсов (string, number, boolean) всегда триггерит ререндер, если значение изменилось
  • Изменение ссылочных пропсов (object, array, function) триггерит ререндер при каждой новой ссылке, даже если содержимое то же
  • Для оптимизации используйте React.memo + useCallback/useMemo
  • В классовых компонентах - PureComponent или ручной shouldComponentUpdate
  • Context API тоже может вызывать ререндер при изменении значения, даже если компонент не использует пропсы

Пример кода

JSX
// Без оптимизации - ререндер при каждом рендере родителя
const Child = ({ data }) => {
console.log('Child re-rendered');
return <div>{data.value}</div>;
};
// С оптимизацией - ререндер только при изменении data
const MemoizedChild = React.memo(({ data }) => {
console.log('MemoizedChild re-rendered');
return <div>{data.value}</div>;
});
const Parent = () => {
const [count, setCount] = useState(0);
// Проблема: каждый рендер создаёт новый объект
const data = { value: 'test' };
return (
<>
<button onClick={() => setCount(c => c + 1)}>Click</button>
<Child data={data} /> // ререндерится всегда
<MemoizedChild data={data} /> // ререндерится всегда из-за новой ссылки
</>
);
};
// Правильное решение с useMemo
const ParentFixed = () => {
const [count, setCount] = useState(0);
const data = useMemo(() => ({ value: 'test' }), []);
return (
<>
<button onClick={() => setCount(c => c + 1)}>Click</button>
<MemoizedChild data={data} /> // не ререндерится при клике
</>
);
};

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

Начните с чёткого "да", затем объясните механизм: родительский ререндер → новые пропсы → shallow comparison → ререндер при различии. Упомяните, что это поведение по умолчанию, и покажите понимание оптимизаций: React.memo, useCallback, useMemo. Для senior-уровня важно подчеркнуть, что ререндер - это не всегда плохо, и оптимизация нужна только при доказанной проблеме производительности. Также стоит упомянуть, что изменение пропсов не вызывает ререндер, если компонент обёрнут в React.memo и пропсы не изменились по ссылке.

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

  • Понимание жизненного цикла React и механизма ререндеринга
  • Знание разницы между примитивными и ссылочными типами в контексте React
  • Умение объяснять, когда и зачем нужны React.memo, useCallback, useMemo
  • Понимание trade-off между производительностью и сложностью кода
  • Способность отличать необходимый ререндер от избыточного

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

  • Утверждение, что изменение пропсов всегда вызывает ререндер (неверно для React.memo)
  • Путаница между ререндером и перерисовкой DOM (re-render vs re-paint)
  • Игнорирование того, что родительский ререндер создаёт новые ссылки на объекты
  • Чрезмерное использование React.memo без измерения производительности
  • Забывание про useCallback при передаче callback-функций в мемоизированный компонент

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

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