PassFront
  1. PassFront
  2. База знаний
  3. Основы React

Как React сравнивает значения?

Основы React

Во всех местах, где React решает «изменилось или нет», используется одно правило — поверхностное сравнение через Object.is (или поэлементное Object.is для наборов значений). Глубоких сравнений React не делает никогда.

Object.is — базовый примитив

Как строгое равенство ===, но Object.is(NaN, NaN) === true и Object.is(+0, -0) === false. Главное:

  • примитивы сравниваются по значению;
  • объекты, массивы, функции — по ссылке: два одинаковых по содержимому объекта не равны.

Где и что сравнивается

  • Сеттер useState / возврат редьюсера: новое значение против старого — равно → рендер пропущен (bail out). Поэтому мутация + сеттер с той же ссылкой «не работает».
  • Deps хуков (useEffect/useMemo/useCallback): поэлементно по позициям; один отличающийся элемент — перезапуск.
  • React.memo / PureComponent: shallow equal — каждый проп (поле state) через Object.is.
  • Context: старое value против нового — изменилось → все потребители ререндерятся.
  • useSyncExternalStore: снапшоты стора.
  • Дифф DOM-props в reconciliation: атрибуты узла поэлементно — в патч идут отличия.

Практические следствия

setUser({ ...user });            // «изменилось» (новая ссылка) — рендер будет
user.name = 'X'; setUser(user);  // «не изменилось» (та же ссылка) — рендера нет
  • Иммутабельность обязательна: изменение = новая ссылка.
  • Инлайн-объекты/функции = «всегда новое» → ломают memo и deps; нужны useMemo/useCallback.
  • Глубокие изменения без новой ссылки невидимы для всех механизмов.

Коротко для собеседования

Везде одно правило: Object.is поверхностно — примитивы по значению, объекты/функции по ссылке; глубокого сравнения нет. Применяется в сеттерах state (bail out), deps хуков, React.memo, контексте и диффе props. Отсюда два столпа React-кода: иммутабельные обновления и стабильные ссылки.

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