The setInterval
function lets us run a function periodically in our JavaScript code by creating a timer.
We may also use setInterval
in our React apps.
Sometimes, we may find that our React component states aren’t updating when we have state updating code in our setInterval
callbacks.
In this article, we’ll look at how to make sure that our states are getting updated when we run state updating code in our setInterval
callback.
Why is the State Not Updating in the setInterval?
If we have code like the following:
import { useEffect, useState } from "react";
export default function App() {
const [time, setTime] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setTime(time + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <div className="App">{time}</div>;
}
Then we may see the value of time
isn’t updating every second.
Instead, it only updates once when the component first mounts.
This is because we passed in an empty array as the value of the 2nd argument in the useEffect
hook.
This means the useEffect
callback runs when the component mounts.
And since time
is 0, time + 1
is 1.
The useEffect
callback doesn’t have access to the latest time
value since it never runs again after it mounts.
Therefore, we can’t just pass in time + 1
to update the value of time
.
To fix this, we need to pass in a callback to setTime
with the current time
value as the parameter and returns the new time
value we want.
To do this, we write:
import { useEffect, useState } from "react";
export default function App() {
const [time, setTime] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setTime((time) => time + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <div className="App">{time}</div>;
}
We pass in a callback to setTime
.
The callback takes the current time
value as the parameter.
And it returns time + 1
so that time
is updated to time + 1
.
Now we should see the time
display updated every second as we expect.
Conclusion
To fix a state that’s not updating in the setInterval
callback, we should pass in a callback to the state setter function to update the state.
This is because the useEffect
callback has to run in order to have access to the latest state values.
One reply on “How to Fix a State That is Not Updating When Using React State Hook in setInterval”
I try to always pass a callback to setState so I don’t forget to do it when it’s actually required.