Выбор ответа Middle Код-ревью обновлено

Утечка в эффекте

Вопрос

Что не так с этим хуком?

function useWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', onResize);
  }, []);
  return width;
}

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

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

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

Коротко

Правильный ответ: Нет очистки: обработчик остаётся после размонтирования, это утечка. Эффект должен вернуть функцию очистки () = window.removeEventListener("resize", onResize), иначе каждое монтирование добавит обработчик, который не снимется.

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

  1. addEventListener нельзя вызывать в эффекте, только в обработчиках
  2. Нужно использовать window.onresize вместо addEventListener
  3. Нет очистки: обработчик остаётся после размонтирования, это утечкаправильный ответ
  4. Надо добавить width в зависимости, иначе значение не обновится

Разбор

Эффект должен вернуть функцию очистки () => window.removeEventListener("resize", onResize), иначе каждое монтирование добавит обработчик, который не снимется. В режиме разработки Strict Mode специально монтирует компонент дважды, чтобы такие ошибки проявлялись. Подписка в эффекте это правильное место. onresize перезапишет чужие обработчики. width в зависимостях вызовет переподписку на каждое изменение без пользы.

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

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