PassFront
  1. PassFront
  2. База знаний
  3. Рендеринг и производительность

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 = не рендерить).

Другие вопросы раздела