DEV Community

Cover image for Creating a React Timer
Raymundo Alva
Raymundo Alva

Posted on

Creating a React Timer

Lately, I decided to practice using intervals in React. Last week, I had built a stopwatch and I immediately thought about building a timer. It is really similar to a stopwatch except it goes backward. So, I thought I would give it a try. Although it seemed just as simple as the stopwatch, building a timer had its own challenges.

I am using React hooks to make this component work. So, first of all, I set a time and start state. The default value for time is zero and false for start. This is what that looks like.

const \[time, setTime\] = useState(0);  
const \[start, setStart\] = useState(false);
Enter fullscreen mode Exit fullscreen mode

In order for the time to display the time in seconds, minutes, and hours, I used a method that is very similar to the one I used with the stopwatch. We apply some math to the value of time and slice the number so that it displays as a two-digit number. This is what it looks like.

let seconds = ("0" + (Math.floor((time / 1000) % 60) % 60)).slice(-2);  
let minutes = ("0" + Math.floor((time / 60000) % 60)).slice(-2);  
let hours = ("0" + Math.floor((time / 3600000) % 60)).slice(-2);
Enter fullscreen mode Exit fullscreen mode

Now we will use our useEffect hook to subtract 10 from the time every second using an interval. This hook will run when the value of start changes. If start is true, the interval will run, and if start is false, the interval is cleared.

useEffect(() => {

  let interval = null;

  if (start) {

    interval = setInterval(() => {

    if (time > 0) {

      setTime(prevTime => prevTime - 10)


    }, 10)

  } else {



  return () => {



}, \[start\])
Enter fullscreen mode Exit fullscreen mode

To set the timer, I created some buttons that will increment the time. Each button will either increment by an hour, a minute, or a second. This will also be the same for the decrementing. To implement this, I created a function that will take an input. If the timer hasn’t started yet, the time can be incremented depending on the button that is pushed.

function adjustTimer(input) {

  if (!start) {

    switch (input) {

      case "incHours":

        setTime(prevTime => prevTime + 3600000)


      case "incMinutes":

        setTime(prevTime => prevTime + 60000)


      case "incSeconds":

        setTime(prevTime => prevTime + 1000)


      case "decHours":

        setTime(prevTime => prevTime - 3600000)

      case "decMinutes":

        setTime(prevTime => prevTime - 60000)


      case "decSeconds":

        setTime(prevTime => prevTime - 1000)






Enter fullscreen mode Exit fullscreen mode

That is all the logic that will give us the main functionality of the timer. Now we just need to render all of that to our screen. The time display will be in between a set of buttons that will help to increment and decrement the time. There will also be a start, stop and reset button. Our return statement will look like this.

return (

  <div className="App">

  <button onClick={() => adjustTimer("incHours")}>&#8679;</button>

  <button onClick={() => adjustTimer("incMinutes")}>&#8679;</button>

  <button onClick={() => adjustTimer("incSeconds")}>&#8679;</button>

  <div>{hours} : {minutes} : {seconds}</div>

  <button onClick={() => adjustTimer("decHours")}>&#8681;</button>

  <button onClick={() => adjustTimer("decMinutes")}>&#8681;</button>

  <button onClick={() => adjustTimer("decSeconds")}>&#8681;</button> <br/><br/>

  <button onClick={() => setStart(true)}>Start</button>

  <button onClick={() => setStart(false)}>Stop</button>

  <button onClick={() => {setStart(false); setTime(0)}}>Reset</button>


Enter fullscreen mode Exit fullscreen mode

This is my timer! To be fair it is not perfect. There are some quirks that need to be fixed. I am thinking of conditionally rendering the buttons so that they only show at different steps of the timer process.

Still, plenty of scope for improvement but it is all that is needed to get started. Happy coding! 😎

Top comments (0)