I'm trying to understand the general advice I've seen regarding React and stale closures.
Specifically, as I understand it, the term "stale closure" is used to describe a scenario where a component and useEffect function are constructed like this
function WatchCount() {
const [count, setCount] = useState(0);
useEffect(function() {
setInterval(function log() {
console.log(`Count is: ${count}`);
}, 2000);
}, []);
return (
<div>
{count}
<button onClick={() => setCount(count + 1) }>
Increase
</button>
</div>
);
}
React calls WatchCount to render a component, and sets the value of the count variable. When javascript calls the log function two seconds later, the count variable will be bound to the count variable from when WatchCount was first called. The value of count won't reflect updates that may have happened on renders of WatchCount that happened in-between the first render and the interval code eventually firing.
The general advice that's given to "solve" this is to list your variable in the dependencies array -- the second argument to useEffect
useEffect(function iWillBeStale() {
setInterval(function log() {
console.log(`Count is: ${count}`);
}, 2000);
}, [count]);
As a javascript programmer, I don't understand how this "solves" the problem. All we've done here is create an array that includes the variable in it, and passed that array to useEffect My naive view is that the count variable in log is still scoped to the first call of WatchCount, and should still be stale.
Am I missing some nuance of javascript's scope here?
Or does this "fix" things because of something that useEffect is doing with those variables?
Or some third thing?