🟨 React
Medium
🕐 15 min

React Timer

Goal: Create a React timer using hooks, effects, and intervals.

💡 Solution Hint

To create a timer you will need:

  1. State: Use useState hooks to store time and useRef to store the interval ID.
  2. Effects: Use the useEffect hook to manage side effects.
  3. Intervals: Use setInterval to update time every second.
  4. Formatting: Convert seconds to MM:SS format for display.
  5. Control: Implement functions to start, stop, and reset the timer.
// Example of using useState and useRef
const [seconds, setSeconds] = useState(0);
const intervalRef = useRef(null);
 
// Example of starting the timer
const startTimer = () => {
  intervalRef.current = setInterval(() => {
    setSeconds(prev => prev + 1);
  }, 1000);
};
👀 Solution
import React, { useState, useRef, useEffect } from 'react';
 
export default function Timer() {
  // State to store seconds
  const [seconds, setSeconds] = useState(0);
  // State to track timer activity
  const [isActive, setIsActive] = useState(false);
  // Ref to store interval ID
  const intervalRef = useRef(null);
 
  // Effect to manage interval
  useEffect(() => {
    if (isActive) {
      intervalRef.current = setInterval(() => {
        setSeconds(prevSeconds => prevSeconds + 1);
      }, 1000);
    } else if (intervalRef.current) {
      clearInterval(intervalRef.current);
    }
 
    // Cleanup interval on component unmount
    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, [isActive]);
 
  // Function to start the timer
  const startTimer = () => {
    setIsActive(true);
  };
 
  // Function to stop the timer
  const stopTimer = () => {
    setIsActive(false);
  };
 
  // Function to reset the timer
  const resetTimer = () => {
    setSeconds(0);
    setIsActive(false);
  };
 
  // Function to format time as MM:SS
  const formatTime = (secs) => {
    const minutes = Math.floor(secs / 60);
    const seconds = secs % 60;
    return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
  };
 
  return (
    <div style={{ textAlign: 'center', margin: '20px' }}>
      <h2>Timer</h2>
      <div style={{ fontSize: '32px', margin: '20px 0', fontFamily: 'monospace' }}>
        {formatTime(seconds)}
      </div>
      <div>
        <button 
          onClick={startTimer}
          disabled={isActive}
          style={{
            padding: '8px 16px',
            margin: '0 5px',
            backgroundColor: '#4CAF50',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: isActive ? 'not-allowed' : 'pointer',
            opacity: isActive ? 0.7 : 1
          }}
        >
          Start
        </button>
        <button 
          onClick={stopTimer}
          disabled={!isActive}
          style={{
            padding: '8px 16px',
            margin: '0 5px',
            backgroundColor: '#f44336',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: !isActive ? 'not-allowed' : 'pointer',
            opacity: !isActive ? 0.7 : 1
          }}
        >
          Stop
        </button>
        <button 
          onClick={resetTimer}
          style={{
            padding: '8px 16px',
            margin: '0 5px',
            backgroundColor: '#2196F3',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          Reset
        </button>
      </div>
    </div>
  );
}

Solution Analysis:

  • State: We use useState hooks to store seconds and timer activity state, and useRef to store the interval ID.
  • Effects: The useEffect hook manages starting and stopping the interval based on activity state.
  • Intervals: setInterval updates the counter every second when the timer is active.
  • Formatting: The formatTime function converts seconds to MM:SS format for display.
  • Control: Implemented functions to start, stop, and reset the timer with appropriate state checks.
  • Styling: Added styles to improve component appearance and indicate button states.

Task Description

You need to create a React timer component. The component should display time in MM:SS format and provide buttons to control the timer.

Key requirements:

  • The initial timer value should be 00:00
  • The “Start” button should start the timer (increment value every second)
  • The “Stop” button should stop the timer
  • The “Reset” button should reset the timer to 00:00
  • The timer should properly manage intervals and avoid memory leaks

Examples

// Basic timer component example
<Timer /> // Displays 00:00 and Start, Stop, Reset buttons
 
// After clicking Start button and waiting 5 seconds
// Displays 00:05 and Start (inactive), Stop, Reset buttons
 
// After clicking Stop button
// Displays 00:05 and Start, Stop (inactive), Reset buttons
 
// After clicking Reset button
// Displays 00:00 and Start, Stop, Reset buttons

Requirements

  • The component should be named Timer
  • Use useState, useEffect, and useRef hooks to manage state and effects
  • Implement functions to start, stop, and reset the timer
  • Add time formatting in MM:SS format
  • Ensure the timer properly clears intervals on stop and unmount
  • Component styling is welcome but not required

🧑‍💻 It's not a bug! It's a feature!

The code editor is intentionally hidden on mobile.

Believe me, it's for the best: I am protecting you from the temptation to code in less-than-ideal conditions. A small screen and a virtual keyboard are not the best tools for a programmer.

📖 Now: Study the task, think through the solution. Act like a strategist.

💻 Later: Sit down at your computer, open the site, and implement all your ideas comfortably. Act like a code-jedi!