Выбор ответа Senior Паттерны компонентов обновлено

children и перерисовка

Вопрос

При движении мыши Tracker меняет состояние. Перерисуется ли ExpensiveTree?

function Tracker({ children }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  return (
    <div onPointerMove={(e) => setPos({ x: e.clientX, y: e.clientY })}>
      <p>{pos.x}, {pos.y}</p>
      {children}
    </div>
  );
}

function App() {
  return (
    <Tracker>
      <ExpensiveTree />
    </Tracker>
  );
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Нет: элемент создан в App и пришёл в children той же ссылкой. Элемент <ExpensiveTree / создаётся при рендере App, а App не перерисовывается.

Варианты ответа

  1. Да, при каждом движении: родитель перерисовался
  2. Нет: элемент создан в App и пришёл в children той же ссылкойправильный ответ
  3. Да, если только ExpensiveTree не обёрнут в memo
  4. Нет: React не перерисовывает компоненты внутри обработчиков событий

Разбор

Элемент <ExpensiveTree /> создаётся при рендере App, а App не перерисовывается. В Tracker приходит тот же объект элемента, и React видит, что он не изменился, поэтому ExpensiveTree не рендерится. Это приём «опустить состояние вниз и передать тяжёлое через children», он работает без memo.

  • Перерисовался Tracker, но не тот, кто создал элемент.
  • memo тут не нужен.
  • Обработчики событий не влияют на правило.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.