Что такое React.memo?
Рендеринг и производительность
React.memo — функция высшего порядка, которая мемоизирует компонент: пропускает его перерендер, если props не изменились по сравнению с прошлым рендером.
Использование
const ProductCard = React.memo(function ProductCard({ product, onBuy }) {
return <div onClick={() => onBuy(product.id)}>{product.title}</div>;
});По умолчанию React при перерендере родителя перерендеривает всех детей независимо от props. React.memo добавляет проверку: props сравниваются поверхностно (Object.is по каждому полю), и если всё совпало — используется прошлый результат рендера.
Второй аргумент — свой компаратор
const Chart = React.memo(ChartInner, (prevProps, nextProps) => {
return prevProps.data.version === nextProps.data.version; // true = НЕ рендерить
});Возврат true означает «props равны, пропустить рендер» (обратно shouldComponentUpdate).
Когда применять
- Компонент рендерится часто с теми же props (строки списков, ячейки таблиц, тяжёлые виджеты).
- Родитель часто обновляется, а данный ребёнок от этих обновлений не зависит.
Почему memo «не работает»
Сравнение поверхностное, поэтому мемоизацию ломают нестабильные ссылки:
- инлайн-функции:
onBuy={() => buy(id)}— каждый рендер новая; нужен useCallback у родителя; - инлайн-объекты/массивы:
style={{ width }}— нужен useMemo; children— это тоже проп, и JSX-дети каждый рендер новые.
Нюансы
- memo не защищает от перерендера из-за собственного state, контекста или хуков компонента — только от props.
- Не стоит оборачивать всё подряд: сравнение props тоже имеет цену, а профит есть только там, где рендер дорогой или частый.
Коротко для собеседования
React.memo кеширует результат рендера компонента и пропускает обновление при поверхностно равных props. Работает в связке с useCallback/useMemo у родителя (иначе ссылки «всегда новые»). Вторым аргументом принимает кастомную функцию сравнения.