Frosted Cupcake
Frosted Cupcake

Reputation: 1970

Using setInterval in React isn't working as expected

I am trying to make a countdown timer using React hooks. The seconds part of the timer is working as expected, but I am encountering an issue when updating the minute part. In the below example, I want the timer to start from 05:00 and then on click of a button update to 04:59, 04:58 and so on. But when I click the button, instead of giving 04:59, it gives me 03:59. Attaching the code for the same below. Please let me know where I am getting it wrong.

import React, { useState } from "react";

const padWithZero = num => {
  const numStr = num.toString();
  return numStr.length === 1 ? "0" + numStr : numStr;
};

const Clock = () => {
  let timer;
  const [mins, setMins] = useState(5);
  const [secs, setSecs] = useState(0);
  const startHandler = () => {
    timer = setInterval(() => {
      setSecs(prevSecs => {
        if (prevSecs === 0) {
          setMins(prevMins => prevMins - 1);
          return 59;
        } else return prevSecs - 1;
      });
    }, 1000);
  };
  return (
    <div>
      <h1>{`${padWithZero(mins)}:${padWithZero(secs)}`}</h1>
      <button onClick={startHandler}>Start</button>
    </div>
  );
};

export default Clock;

Upvotes: 0

Views: 74

Answers (1)

lavor
lavor

Reputation: 1877

I don't know the exact reason why it decreases your minutes two times from 5 to 4 and from 4 to 3.

But I modified your code and added resetting feature - each click to button will resets timer back to initial 5:00. And now it works correctly:

import React, { useState } from "react";

const padWithZero = num => {
  const numStr = num.toString();
  return numStr.length === 1 ? "0" + numStr : numStr;
};

const INIT_SECS = 0;
const INIT_MINS = 5;

const Clock = () => {
    let timer;
    const [mins, setMins] = useState(INIT_MINS);
    const [secs, setSecs] = useState(INIT_SECS);
    const [storedTimer, setStoredTimer] = useState(null);

    const startHandler = () => {
        if (storedTimer) {
            clearInterval(storedTimer);
            setMins(INIT_MINS);
            setSecs(INIT_SECS);
        }
        const newTimer = setInterval(() => {
            setSecs(prevSecs => {
                if (prevSecs === 0) {
                    setMins(prevMins => prevMins - 1);
                    return 59;
                } else return prevSecs - 1;
            });
        }, 1000);

        setStoredTimer(newTimer);
    };

    return (
        <div>
            <h1>{`${padWithZero(mins)}:${padWithZero(secs)}`}</h1>
            <button onClick={startHandler}>Start</button>
        </div>
    );
};
export default Clock;

Upvotes: 1

Related Questions