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

Объясни, будет ли перерисовка компонента, если в setState передать тот же state: от чего это зависит и почему.

Рендеринг и производительность

Зависит от того, что значит «тот же»: React сравнивает старое и новое значение через Object.is. Тот же примитив или та же ссылка — перерендера не будет; новый объект с тем же содержимым — будет.

Функциональные компоненты (useState)

const [count, setCount] = useState(5);
setCount(5);               // Object.is(5, 5) → рендер пропущен

const [user, setUser] = useState({ name: 'Аня' });
setUser(user);             // та же ссылка → рендер пропущен
setUser({ ...user });      // НОВАЯ ссылка → рендер будет, хоть содержимое то же

Правило: Object.is(старое, новое) → обновление игнорируется (bail out). Поэтому мутировать и передавать тот же объект бессмысленно — React не увидит изменений, а копировать без изменений — лишний рендер.

Нюанс: рендер «на всякий случай»

Даже при равном значении React иногда вызывает рендер этого компонента ещё один раз (прежде чем «сдаться»), но не рендерит детей и не коммитит в DOM — на практике это не важно, но в console.log можно увидеть.

Классовые компоненты (setState)

this.setState({ count: 5 }) вызывает перерендер всегда, даже с тем же значением: setState мерджит объект и не сравнивает содержимое. Отсюда shouldComponentUpdate/PureComponent — ручная отмена лишних рендеров.

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

  • Иммутабельность обязательна: изменение через мутацию + setState(тот же объект) = потерянное обновление.
  • Возврат того же значения из функционального сеттера (setX((x) => x)) — легальный способ «не обновлять».
  • В редьюсере useReducer вернуть прежний state → рендер пропущен.

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

useState сравнивает через Object.is: тот же примитив/ссылка — рендера нет, новый объект с тем же содержимым — рендер есть. В классах setState рендерит всегда (без сравнения) — там спасают PureComponent/shouldComponentUpdate. Отсюда два правила: не мутировать и не создавать новые ссылки без надобности.

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