🟨 React
Легкая
🕐 1 story point

React: Секундомер / таймер — старт, стоп, сброс

Реализуй секундомер с кнопками запуска, остановки и сброса. Время отображается в формате мм:сс.

Используй только хук useState. Другие хуки (например useEffect, useRef) не допускаются.

Александр, тимлид React-стажировки

Продуктовый фокус. Точное время — база аналитики продуктивности. Освой старт/стоп, сброс и очистку ресурсов.

Что нужно сделать

  • Используй только хук useState; не применяй другие хуки (useEffect, useRef и т.д.).
  • Создай состояния: isRunning и elapsed (секунды).
  • Запуск: стартует интервал setInterval, который раз в секунду увеличивает elapsed.
  • Остановка: очищает интервал и переводит isRunning в false.
  • Сброс: очищает интервал, ставит elapsed = 0, isRunning = false.
  • Форматируй вывод времени как мм:сс.

Финальный вид

Карточка со счётчиком времени и тремя кнопками: «Старт», «Стоп», «Сброс». Пример: Stopwatch UI

💡 Подсказка
  • Используй только состояние: isRunning, elapsed и timerId.
  • Запускай интервал в handleStart: const id = setInterval(() => setElapsed(prev => prev + 1), 1000), сохраняй id в состоянии.
  • Останавливай через clearInterval(timerId) и сбрасывай timerId в null.
  • Сброс: останавливает интервал, ставит elapsed = 0, isRunning = false.
  • Дополнительно: отключай кнопку «Старт», пока идёт отсчёт, чтобы не создавать несколько интервалов.
👀 Решение
import React, { useState } from 'react';
import './styles.css';
 
export function Stopwatch() {
  const [isRunning, setIsRunning] = useState(false);
  const [elapsed, setElapsed] = useState(0);
  const [timerId, setTimerId] = useState(null);
 
  function handleStart() {
    if (isRunning) return;
    const id = setInterval(() => {
      setElapsed((prev) => prev + 1);
    }, 1000);
    setTimerId(id);
    setIsRunning(true);
  }
 
  function handleStop() {
    if (timerId) {
      clearInterval(timerId);
      setTimerId(null);
    }
    setIsRunning(false);
  }
 
  function handleReset() {
    if (timerId) {
      clearInterval(timerId);
      setTimerId(null);
    }
    setIsRunning(false);
    setElapsed(0);
  }
 
  function format(seconds) {
    const m = Math.floor(seconds / 60);
    const s = seconds % 60;
    return String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0');
  }
 
  return (
    <article className="card" data-testid="stopwatch-card">
      <header>
        <h2 className="title">TimeSprint: секундомер</h2>
        <p className="subtitle">Запуск, остановка и сброс времени</p>
      </header>
 
      <p className="display" aria-label="time">{format(elapsed)}</p>
 
      <div className="row">
        <button className="button" onClick={handleStart} disabled={isRunning}>Старт</button>
        <button className="button" onClick={handleStop} disabled={!isRunning}>Стоп</button>
        <button className="button" onClick={handleReset}>Сброс</button>
      </div>
    </article>
  );
}
 
export default function App() {
  return (
    <main className="challenge-container">
      <section>
        <Stopwatch />
      </section>
    </main>
  );
}

🧑‍💻 Это не баг! Это фича!

Редактор кода намеренно скрыт на мобильном.

Поверь, так лучше: я оберегаю тебя от искушения писать код в неидеальных условиях. Маленький экран и виртуальная клавиатура — не лучшие помощники для программиста.

📖 Сейчас: Изучи задачу, продумай решение. Действуй как стратег.

💻 Потом: Сядь за компьютер, открой сайт и реализуй все идеи с комфортом. Действуй как код-джедай!