Выбор ответа Middle Области видимости и замыкания спрашивают часто обновлено

Счётчик в setInterval застревает на 1

Вопрос

Счётчик в React-компоненте показывает 0, потом 1 и дальше не растёт. Почему?

const [count, setCount] = useState(0);
useEffect(() => {
  const id = setInterval(() => setCount(count + 1), 1000);
  return () => clearInterval(id);
}, []);

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

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

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

Коротко

Правильный ответ: Колбэк замкнул count первого рендера (0) и каждый раз ставит 0 + 1. Эффект с пустым массивом зависимостей выполнился один раз и создал колбэк, который замкнул count первого рендера.

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

  1. setInterval в React срабатывает только один раз, а потом его надо перезапускать
  2. React объединяет обновления, и все вызовы setCount кроме первого отбрасываются
  3. clearInterval из функции очистки вызывается сразу после первого тика
  4. Колбэк замкнул count первого рендера (0) и каждый раз ставит 0 + 1правильный ответ

Разбор

Эффект с пустым массивом зависимостей выполнился один раз и создал колбэк, который замкнул count первого рендера. Новые рендеры создают новые count, но колбэк их не видит: это устаревшее замыкание. Каждый тик ставит 1, а одинаковое значение React не рендерит заново. Исправление: функциональное обновление setCount(c => c + 1). Интервал работает исправно и не очищается раньше размонтирования. Батчинг тут ни при чём: вызовы приходят в разные тики.

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

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