DEV Community

Michael Burrows
Michael Burrows

Posted on • Originally published at w3collective.com

Create a custom React stopwatch timer component

In this tutorial we’ll be creating a React stopwatch timer component. The completed stopwatch component will display minutes, seconds, and milliseconds with start, stop, and reset functionality.

Let’s get started by setting up a dev environment using Create React App:

npx create-react-app react-stopwatch

Next create a new Stopwatch.js file in the /src folder:

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

const Stopwatch = () => { 
  //...
};

export default Stopwatch;
Enter fullscreen mode Exit fullscreen mode

We’ll be using two React Hooks, firstly useState which allows us to store state in a function based component. It’ll be used to store the stopwatch time and also whether or not the stopwatch is running. The useEffect Hook checks if the timer is running and if so updates the time.

In the Stopwatch() function we’ll first declare variables for the time and running states:

const Stopwatch = () => {
  const [time, setTime] = useState(0);
  const [running, setRunning] = useState(false);  
  //...
};
Enter fullscreen mode Exit fullscreen mode

Then we’ll calculate the time using a useEffect() Hook & setInterval() method:

const Stopwatch = () => {
  const [time, setTime] = useState(0);
  const [running, setRunning] = useState(false);
  useEffect(() => {
    let interval;
    if (running) {
      interval = setInterval(() => {
        setTime((prevTime) => prevTime + 10);
      }, 10);
    } else if (!running) {
      clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [running]);
  //...
};
Enter fullscreen mode Exit fullscreen mode

To complete the component we’ll output the time along with control buttons:

const Stopwatch = () => {
  const [time, setTime] = useState(0);
  const [running, setRunning] = useState(false);
  useEffect(() => {
    let interval;
    if (running) {
      interval = setInterval(() => {
        setTime((prevTime) => prevTime + 10);
      }, 10);
    } else if (!running) {
      clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [running]);
  return (
    <div className="stopwatch">
      <div className="numbers">
        <span>{("0" + Math.floor((time / 60000) % 60)).slice(-2)}:</span>
        <span>{("0" + Math.floor((time / 1000) % 60)).slice(-2)}:</span>
        <span>{("0" + ((time / 10) % 100)).slice(-2)}</span>
      </div>
      <div className="buttons">
        <button onClick={() => setRunning(true)}>Start</button>
        <button onClick={() => setRunning(false)}>Stop</button>
        <button onClick={() => setTime(0)}>Reset</button>       
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

The time is calculated by dividing the time by the number of milliseconds for each unit of time. We then use the remainder operator % to calculate if the time is divisible by 60 for seconds, 60 for minutes and, 100 for milliseconds. For example 1 minute 20 seconds is 80000 milliseconds so to calculate the seconds we do (80000 / 1000) % 60 = 20. Without the remainder operator (80000 / 1000) = 80 we just get the total seconds.

Finally replace the contents of App.js to import and load the stopwatch component:

import Stopwatch from "./Stopwatch";

const App = () => {
  return (
    <div className="App">
      <Stopwatch />
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

That’s all for this tutorial, hopefully it’ll serve as a starting point for you to build more complex time based applications. Whilst you’re here be sure to checkout our ever expanding collection of practical React tutorials.

Latest comments (2)

Collapse
 
andrewbaisden profile image
Andrew Baisden

Great tutorial thanks for sharing the code.

Collapse
 
stormytalent profile image
StormyTalent

Perfect!