Логотип YeaHub

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

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

Тренажёр

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

Обучение

Навыки

Войти

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

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

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про React: stopwatch, timer, setinterval

Как реализовать компонент-секундомер, который обновляется раз в секунду?

Вопрос проверяет умение работать с таймерами в React, корректно управлять жизненным циклом и избегать типичных багов с интервалами.

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

Проще всего хранить “прошедшие секунды” в useState, а запуск обновления сделать в useEffect через setInterval. Внутри интервала увеличивать значение каждую секунду через функциональное обновление setState(prev => prev + 1). Обязательно вернуть функцию очистки, чтобы остановить интервал при размонтировании. Для более точного секундомера лучше хранить startTime в useRef и пересчитывать прошедшее время от реального времени, чтобы уменьшить “дрейф”.

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

Секундомер можно сделать “простым” (приблизительным) и “более точным” (через реальное время).

Вариант 1: простой секундомер (инкремент раз в секунду)

Идея простая: раз в 1000 мс увеличиваем счётчик.

import { useEffect, useState } from "react";

export function Stopwatch() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = window.setInterval(() => {
      setSeconds((s) => s + 1);
    }, 1000);

    return () => window.clearInterval(id);
  }, []);

  return <div>{seconds}s</div>;
}
  1. Почему используется setSeconds((s) => s + 1)

    • это защищает от “устаревшего значения” в замыкании и работает стабильно.

Вариант 2: более точный секундомер (меньше дрейфа)

Интервалы в браузере могут “плыть” (вкладка неактивна, нагрузка, таймеры троттлятся). Поэтому можно хранить время старта и вычислять прошедшее время от Date.now().

import { useEffect, useRef, useState } from "react";

export function StopwatchAccurate() {
  const startRef = useRef<number>(Date.now());
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = window.setInterval(() => {
      const diffMs = Date.now() - startRef.current;
      setSeconds(Math.floor(diffMs / 1000));
    }, 1000);

    return () => window.clearInterval(id);
  }, []);

  return <div>{seconds}s</div>;
}
  1. Что даёт useRef

    • значение startRef.current сохраняется между рендерами и не вызывает ререндер само по себе.

Вывод

Для простых UI-задач достаточно инкремента раз в секунду, но для “настоящего” секундомера лучше считать секунды от реального времени, чтобы таймер меньше “уезжал”.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • React

    React

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

#stopwatch

#timer

#setinterval

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