I am building a piece of code in which I need 2 nested components to update a state variable:
function Test() {
const [test, setTest] = useState()
async function wait() {
await new Promise((res, rej) => setTimeout(res, 1000))
console.log("after 1s waiting, test is", test)
}
async function setTest1() {
await wait()
setTest("test1")
}
async function setTest2() {
setTest("test2")
}
useEffect(() => console.log("after being updated, test is", test), [test]);
return (
<div>
<div onClick={setTest1}>
<span onClick={setTest2}>update test</span>
</div>
</div>
)
}
When clicking "update test", setTest2 is called then setTest1 is called. This happens asynchronously: setTest1 might be called before setTest2 ends.
First, setTest2 and setTest1 are called. Then setTest2 updates test, giving it the value "test2". At this point setTest1 is still running. It is waiting 1s before continuing. After 1s, the value of test is undoubtedly "test2". Is it not?...
When logging the value of test after waiting 1s, I would expect the result to be "test2", since the state has already been updated to "test2". However, the result is not "test2", but undefined, as if it had not been updated by setTest2.
This piece of code logs this:
after being updated, test is undefined
after being updated, test is test2
after 1s waiting, test is undefined <--- what ???
after being updated, test is test1
It looks like some kind of scoping mechanism, but I am unable to find an explanation for it.
Why is test's value not test2 when logged in the wait call inside of the setTest1 call?