Memo проверяет равенство props по значению или по референсу?
Рендеринг и производительность
React.memo сравнивает props поверхностно: примитивы — по значению, объекты, массивы и функции — по ссылке (референсу). Механизм — Object.is по каждому пропу.
Что это значит
const Card = React.memo(CardInner);
<Card title="Привет" /> // строка: по значению → равны → рендер пропущен
<Card user={{ name: 'Аня' }} /> // объект-литерал: новая ссылка → «изменилось» → рендер
<Card onClick={() => save()} /> // новая функция → «изменилось» → рендерОдинаковое содержимое не означает равенства: {a:1} !== {a:1}.
Практические следствия
- Инлайн-объекты, массивы, стили и стрелки в JSX ломают memo — нужны
useMemo/useCallbackу родителя или константы вне компонента. children— тоже проп, и JSX-дети пересоздаются каждый рендер: memo с children обычно бесполезен.- Мутация внутри объекта props невидима: ссылка та же, memo пропустит рендер, и UI не обновится. Отсюда требование иммутабельности.
Как изменить правило
Второй аргумент memo — свой компаратор:
React.memo(Chart, (prev, next) => prev.data.revision === next.data.revision);
// true = props «равны», рендер пропуститьГлубокое сравнение возможно, но часто дороже самого рендера — обычно это сигнал стабилизировать ссылки, а не сравнивать глубже.
Коротко для собеседования
По референсу (для объектов, массивов, функций) и по значению для примитивов — поверхностное сравнение через Object.is. Поэтому инлайн-объекты и стрелки ломают memo, а мутации внутри объекта делают изменения невидимыми. Изменить правило можно вторым аргументом memo (true = не рендерить).