How to update state using setInterval on functional components in React
Asked Answered
K

2

5

I am trying to implement a countdown, but the state is not being update as expected. It stays stuck on initial value 30. I have no clue how to solve it. Can anyone help me please?

  const [timer, setTimer] = useState(30);

  function handleTimer() {
    const interval = setInterval(() => {
      setTimer((count) => count - 1);
      if (timer <= 0) {
        clearInterval(interval);
      }
    }, 1000);
  }

  useEffect(() => {
    handleTimer();
  }, []);
Kickback answered 19/2, 2022 at 12:7 Comment(1)
Hi @Kelson Batista,I edited the answer, please check againNeighborhood
L
9

The problem is about javascript closures, you can read more about it here

Also, Dan has a full detailed article talking about this specific problem. I strongly suggest you read it.

And here is a quick solution and demonstration for your problem. First of all, the useEffect will be executed every time the component is remount. And this could happen in many different scenarios depending on your code. Hence, The useEffect starts fresh and closes on new data every time.

So all we need is to save our values into ref so we can make use of the same reference every re-render.

// Global Varibales
const INITIAL_TIMER = 30;
const TARGET_TIMER = 0;
// Code refactoring
  const [timer, setTimer] = useState(INITIAL_TIMER);
  const interval = useRef();

  useEffect(() => {
    function handleTimer() {
      interval.current = setInterval(() => {
        setTimer((count) => count - 1);
      }, 1000);
    }

    if (timer <= TARGET_TIMER && interval.current) {
      clearInterval(interval.current);
    }
    if (timer === INITIAL_TIMER) {
      handleTimer();
    }
  }, [timer]);
Loge answered 19/2, 2022 at 13:37 Comment(1)
It worked like a charm @AhmedTarek, perfect explanation. Thank you so much!Kickback
O
3

You can find here a more generic hook to handle the setInterval efficiently in react with pause and limit the number of iterations:

https://github.com/oulfr/react-interval-hook

Oldfashioned answered 19/10, 2022 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.