You may recognize the counter example extracted from React documentation, to which I added a new button. When this button is clicked, an alert is shown five seconds later, with the current value of the counter. Or that’s what you could imagine, unfortunately the displayed value is not the current one.

Let’s say you click the button when the counter is 5, then immediately after you click the increment button three times. You expect the alert to display 8, yet it displays 5. This is because in the function given to setTimeout, counter’s value is 5, and there is no reason for it to be updated (React hooks are not that magical). It’s plain JavaScript closure and scope concern, so obviously we need to find another way to do what we want.

The answer: refs and the hook useRef. The idea is to use a ref for the counter; it would be updated it each time counter is, and we would use its current value in the function given to setTimeout.

So first we declare our ref, with current counter value as initial value:

const counterRef =useRef(counter)

Then we want to update it every time counter is updated, so we can use useEffect:

useEffect(()=>{ counterRef.current = counter },[counter])

Finally, we only have to use counterRef.current in out timeout function:

I’m not fully sure this is the best way to address this concern of getting a state value in the future, although it seems to work fine. Were you confronted to the same kind of issue with state and hooks? Do you see another way to do, or any issue with this one?