user11783025
user11783025

Reputation:

How to display countdown timer in React

How can I show countdown timer in minute and seconds. right now I am able to show the timer in seconds, only but I want to display both minutes and seconds both.

Currently my countdown timer is showing in this way Countdown: 112 but I want it to be like Countdown: 1: 52

import React from "react";

export default function App() {
  const [counter, setCounter] = React.useState(120);
  React.useEffect(() => {
    counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
  }, [counter]);

  return (
    <div className="App">
      <div>Countdown: {counter === 0 ? "Time over" : counter}</div>
    </div>
  );
}

Upvotes: 1

Views: 4130

Answers (4)

Stefano Di Cecco
Stefano Di Cecco

Reputation: 101

Import hooks from import stage:

Hooks react

  import React, { useState, useEffect } from "react"; 
  
  export default function App() {
    const [counter, setCounter] = useState(120);
    useEffect(() => {
      counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
    }, [counter]);
    
    return (
      <div className="App">
        <div>Countdown: {counter === 0 ? "Time over" : counter}</div>
      </div>
     );
    }

Upvotes: 2

Clarity
Clarity

Reputation: 10873

Here's a complete solution with formatting time:

// Prepend `0` for one digit numbers. For that the number has to be
// converted to string, as numbers don't have length method
const padTime = time => {
  return String(time).length === 1 ? `0${time}` : `${time}`;
};

const format = time => {
  // Convert seconds into minutes and take the whole part
  const minutes = Math.floor(time / 60);

  // Get the seconds left after converting minutes
  const seconds = time % 60;

  //Return combined values as string in format mm:ss
  return `${minutes}:${padTime(seconds)}`;
};

export default function App() {
  const [counter, setCounter] = React.useState(120);
  React.useEffect(() => {
    let timer;
    if (counter > 0) {
      timer = setTimeout(() => setCounter(c => c - 1), 1000);
    }

    return () => {
      if (timer) {
        clearTimeout(timer);
      }
    };
  }, [counter]);

  return (
    <div className="App">
      {counter === 0 ? "Time over" : <div>Countdown: {format(counter)}</div>}
    </div>
  );
}

A few notes about your original code:

  1. Since the next value of counter depends on the previous one it's better to use the functional form of setState.
  2. It's a good practice to clear timeout when component unmounts.

Upvotes: 7

Titulum
Titulum

Reputation: 11466

This can be done like so:

import React from "react";

export default function App() {
  const [counter, setCounter] = React.useState(120);
  React.useEffect(() => {
    counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
  }, [counter]);

  return (
    <div className="App">
      <div>Countdown: {counter === 0 ? "Time over" : counter}</div>
    </div>
  );
}

Upvotes: 0

Sandy
Sandy

Reputation: 11687

Changing your setCounter method to following should work.

React.useEffect(() => {
    counter !== 'Time Over' && setTimeout(() => setCounter(counter > 1 ? counter - 1 : 'Time Over'), 1000);
}, [counter]);

Upvotes: 0

Related Questions