Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про JavaScript: React, useState, useEffect, useRef, setInterval, closure

Как избежать устаревших значений состояния внутри setInterval?

Проверяет понимание проблемы замыканий и устаревших значений состояния при использовании setInterval в React.

Короткий ответ

Проблема возникает из-за замыкания, которое захватывает значение состояния на момент создания колбэка setInterval. Чтобы избежать этого, можно использовать функциональную форму setState (prev => prev + 1), использовать useRef для хранения актуального значения или пересоздавать интервал при изменении зависимости через useEffect.

Длинный ответ

Проблема устаревших значений в setInterval

Когда вы используете setInterval внутри useEffect или обработчика события, колбэк интервала создается один раз и захватывает значение состояния на момент своего создания. Это классическая проблема замыканий в JavaScript. Например, если вы пишете setInterval(() => setCount(count + 1), 1000), то count внутри колбэка всегда будет равен тому значению, которое было при первом рендере, а не обновленному.

Решение с функциональным обновлением

Самый простой способ — использовать функциональную форму setState, которая получает предыдущее состояние как аргумент:

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

Это работает, потому что React гарантирует, что prev будет актуальным значением на момент выполнения обновления.

Решение с useRef

Если вам нужно использовать текущее значение состояния внутри колбэка (например, для логирования или условий), используйте useRef для хранения актуального значения:

const countRef = useRef(count);
countRef.current = count;

useEffect(() => {
  const id = setInterval(() => {
    console.log(countRef.current);
  }, 1000);
  return () => clearInterval(id);
}, []);

useRef не вызывает перерендер и всегда содержит актуальное значение, так как вы обновляете его при каждом рендере.

Решение с пересозданием интервала

Можно добавить count в зависимости useEffect, чтобы интервал пересоздавался при каждом изменении состояния:

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

Этот подход менее эффективен, так как интервал будет постоянно создаваться и очищаться, но он интуитивно понятен.

Вывод

Для простого инкремента используйте функциональное обновление setState. Если нужно читать текущее состояние внутри колбэка — применяйте useRef. Пересоздание интервала через зависимости — запасной вариант, когда другие методы не подходят.

Frontend developer

tech
tech
tech
tech
tech
tech
tech
tech
tech

Ментор по Frontend

Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства

Записаться на консультацию

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • JavaScript

    JavaScript

  • React

    React

Ключевые слова

#React

#useState

#useEffect

#useRef

#setInterval

#closure

Подпишись на React Developer в телеграм

Frontend developer

tech
tech
tech
tech
tech
tech
tech
tech
tech

Ментор по Frontend

Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства

Записаться на консультацию