setInterval Gotchas with React Hooks
Divyansh Gothwal
Posted on May 25, 2023
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>;
}
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.
Let's see why this code is not correct?
Below is the flow of this react component.
- Component mounts/renders
- UseEffect will be called which sets setInterval with a callback function.
- When setInterval is executed with callback function, it has closure with value of count=0.
- 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>;
}
Posted on May 25, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.