Beware of Stale Closure Data in React
Something we continually take for granted is that setState
is actually an asynchronous method, and closures in JavaScript can get end up getting a stale version of state (if they’re using any) because of this.
This is particularly painful when your next version of some state depends on the previous version (Eg. A counter + 1).
To ensure that closures don’t experience issues like this, you can provide a callback to setState
instead of a fixed value.
Eg. Instead of:
[count, setCount] = useState(0);
const increment = () => setCount(count + 1);
Do this:
[count, setCount] = useState(0);
const increment = () => setCount((prevCount) => prevCount + 1);
Your increment closure is now a little more resilient to asynchronous events, and since it doesn’t refer to some stale version of state, it will update the next version accordingly.
Tweet