1

I want to have a countdown timer that counts from 60 to zero when the stage of program reaches two. Here's my code:

const [timer, setTimer] = useState(60)
useEffect(() => {
        if (stage === 2) {
            const interval = setInterval(() => {
                console.log(timer)
                setTimer(timer - 1)
                if (timer === 1) {
                    clearInterval(interval)
                }
            }, 1000)
        }
    }, [stage])

and i have a div like below that just shows the counter value

<div>{timer}</div>

in my setInterval, when i use console.log(timer) it always prints out 60. But inside the div, the value starts with 60 and in the next second it will always be 59. What am i doing wrong here?

3
  • 1
    you need to set the state and use the state so that component renders. Commented Feb 24, 2021 at 10:06
  • 1
    You are console.loging before you -1 from the timer, so even if it was synchronous it would print out 60. But as setTimer is asynchronous, you can't rely on the log ever showing the new value immediately, you would need an effect listening for changes to timer. Commented Feb 24, 2021 at 10:06
  • i know that. All i'm saying is, why the state won't get updated? Commented Feb 24, 2021 at 10:22

1 Answer 1

2

You have closure on time === 60 value, use functional update instead.

For the same reason, you should have another useEffect for canceling the interval:

const intervalId = useRef();

useEffect(() => {
  if (stage === 2) {
    intervalId.current = setInterval(() => {
      setTimer((prevTimer) => prevTimer - 1);
    }, 1000);
  }
}, [stage]);

useEffect(() => {
  console.log(timer);
  if (timer === 1) {
    clearInterval(intervalId.current);
  }
}, [timer]);

Check similar question: setInterval counter common mistakes.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.