DEV Community

Cover image for setInterval Gotchas with React Hooks
Divyansh Gothwal
Divyansh Gothwal

Posted on • Updated on

setInterval Gotchas with React Hooks

In this article we are going to understand Gotchas of using setInterval callback function to update state.

For example we have to build a react where we start timer when application loads.

Below the code that everyone who has basic knowledge react will write it.

function WrongCountUpdate() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return <div>Wrong count update: {count}</div>;
}
Enter fullscreen mode Exit fullscreen mode

There is bug in the above code and this has nothing to do with react this is how javascript works.
let's have a look at this live.
Below is the Codesandbox link for this.

Counter update

Let's see why this code is not correct?

Below is the flow of this react component.

  1. Component mounts/renders
  2. UseEffect will be called which sets setInterval with a callback function.
  3. When setInterval is executed with callback function, it has closure with value of count=0.
  4. When state updates setInterval callback function is not aware of change of count variable and its closure still has value of count=0 and when setCount is executed with 0+1 ==> 1 thus our count is always one.

To fix this issue we just have to make one change in our setCount instead of passing value to it, we pass a callback function whose input argument is previous count value and return new state.

React ensures that argument of this function has correct previous value.

Below is the correct code for this.

function CorrectCountUpdate() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount((prevCount) => prevCount + 1);
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return <div>Correct count update: {count}</div>;
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)