Как происходит сравнение props в React?
Компоненты
Сравнение props в React происходит в двух разных местах, и работает по-разному: при диффе DOM-элементов (всегда) и при решении «рендерить ли компонент» (только если он мемоизирован).
По умолчанию: props компонентов НЕ сравниваются
Обычный компонент перерендеривается вместе с родителем без всякой проверки props. Распространённое заблуждение — «React сравнил props и решил обновить»; на деле решение «рендерить» каскадное, а сравнение включается только у React.memo/PureComponent.
React.memo: поверхностное сравнение
const Card = React.memo(CardInner);При рендере родителя React сравнивает каждый проп старого и нового набора через Object.is:
- примитивы — по значению;
- объекты, массивы, функции — по ссылке:
{a: 1} !== {a: 1}.
Отсюда правило: инлайн-объекты/функции/JSX-children ломают memo — ссылки каждый рендер новые. Кастомное сравнение — вторым аргументом memo: React.memo(Comp, (prev, next) => boolean).
DOM-элементы: дифф атрибутов
Для host-элементов (div, input) reconciliation сравнивает старые и новые props, чтобы вычислить минимальные правки атрибутов/стилей — это происходит всегда, но влияет на объём DOM-операций, а не на вызов компонентов.
Где ещё то же сравнение
Object.is используется и в зависимостях useEffect/useMemo/useCallback, и при проверке «то же ли значение передали в сеттер». Единая механика: ссылочное равенство, глубоких сравнений React не делает никогда (дорого).
Коротко для собеседования
По умолчанию props не сравниваются — дети рендерятся каскадом. Сравнение включает React.memo: поверхностное, каждый проп через Object.is (объекты/функции — по ссылке, поэтому нужны useMemo/useCallback). Глубокого сравнения в React нет нигде; для DOM-узлов дифф props определяет минимальные правки атрибутов.