React unexpectedly keeps an old value of a variable produced by React.useState(...). I press the button [1] and then [2]. In 3000 ms I expect to see "null"
in the alerting message, but still see "42"
.
Wrapping handleDisplay
into React.useCallback
with dependency on [val]
does not help.
function App() {
const [val, setVal] = React.useState(42)
const handleHide = () => {
setVal(null)
}
const handleDisplay = () => {
setTimeout(() => {
alert(val)
}, 3000)
}
return (
<div>
<p>VAL: {val ? val : 'null'}</p>
<button onClick={handleDisplay}>[1] display value with delay</button>
<button onClick={handleHide}>[2] hide immediately</button>
</div>
)
}
At the same time — value on the page (rendered via VAL: { val ? val : 'null' }
) is correct, it is "null"
as expected.
Any ideas about what do I do wrong, and how can I get "null"
in my alert(...)
?
P.S. Here is a sandbox with a live example https://codesandbox.io/s/react-usestate-bug-24ijj
At the first render, val is just a constant number with the value 42 that can never change. This is the value passed to setTimeout when you click button 1. Clicking button 2 before 3 seconds have passed will cause a new render in which a new instance of val has the value null, but this will not affect the value bound in the first render. You probably want to read up on the useEffect hook. Dan Abramov has a great, but long article here, that mentions just this issue: https://overreacted.io/a-complete-guide-to-useeffect/