> Как сделать так, чтобы React компонент рендерился только при изменении определенного пропса (React)

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

Компании: EdenAI

Стек: React

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

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

Для контроля рендера React компонента при изменении определённого пропса используйте React.memo с кастомной функцией сравнения. Вторым аргументом передаётся areEqual(prevProps, nextProps), где вы сравниваете только нужный пропс. Если функция возвращает true - рендер не произойдёт. Альтернатива: useMemo внутри компонента для мемоизации возвращаемого JSX по зависимостям.

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

React.memo - это HOC, который предотвращает ре-рендер компонента, если пропсы не изменились (поверхностное сравнение). По умолчанию он сравнивает все пропсы, но вы можете переопределить логику через второй аргумент - функцию areEqual. Она получает предыдущие и новые пропсы и должна вернуть true, если компонент не нужно обновлять.

Пример: React.memo(Component, (prev, next) => prev.specificProp === next.specificProp). Теперь компонент будет рендериться только при изменении specificProp, игнорируя изменения других пропсов.

Важно: функция сравнения должна быть чистой и быстрой. Не используйте глубокое сравнение объектов без необходимости - это снижает производительность. Для сложных структур данных применяйте useMemo для стабилизации ссылок на пропсы.

На практике

В реальных проектах такой подход полезен для:

  • Оптимизации списков с большим количеством элементов, где каждый элемент реагирует только на свои данные
  • Компонентов, которые зависят от внешних данных (например, графики или анимации)
  • Избежания лишних ре-рендеров при передаче колбэков или конфигурационных объектов

Помните: React.memo работает только для функциональных компонентов. Для классовых используйте shouldComponentUpdate или PureComponent (но PureComponent сравнивает все пропсы поверхностно, без кастомной логики).

Пример кода

JSX
import React, { memo } from 'react';
const ExpensiveChart = memo(
({ data, onPointClick, theme }) => {
// рендер графика
return <Chart data={data} onClick={onPointClick} />;
},
(prevProps, nextProps) => {
// рендерим только при изменении data
return prevProps.data === nextProps.data;
}
);
// Использование
function Parent() {
const [count, setCount] = useState(0);
const [chartData, setChartData] = useState([1, 2, 3]);
return (
<>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveChart data={chartData} onPointClick={() => {}} theme="dark" />
</>
);
}

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

Начните с React.memo как основного инструмента. Объясните, что второй аргумент позволяет точно контролировать, какие пропсы влияют на рендер. Упомяните, что это trade-off: кастомное сравнение добавляет вычислительную нагрузку, поэтому его стоит применять только при реальных проблемах производительности. Добавьте, что для классовых компонентов есть shouldComponentUpdate. Если спросят про хуки - скажите, что useMemo может мемоизировать результат, но не предотвращает рендер самого компонента.

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

  • Понимание механизма ре-рендера в React
  • Умение оптимизировать производительность без premature optimization
  • Знание разницы между React.memo, useMemo, shouldComponentUpdate
  • Способность объяснить, когда кастомное сравнение оправдано, а когда нет
  • Понимание поверхностного vs глубокого сравнения

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

  • Использование React.memo без второго аргумента, когда нужно игнорировать изменения некоторых пропсов
  • Передача в areEqual функции, которая делает глубокое сравнение больших объектов на каждый рендер - это убивает производительность
  • Забывание, что React.memo не влияет на дочерние компоненты - если родитель ре-рендерится, дети всё равно могут обновиться
  • Применение React.memo к компонентам с пропсами-функциями без их стабилизации через useCallback - сравнение будет всегда false

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

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