This is the code written
function App() {
const [number, setNumber] = useState(1);
const mapper = {
1: 'One',
2: 'two',
3: 'three'
}
const setFirst = () => {
setNumber(1);
console.log(number);
console.log(mapper[number]);
}
const setSecond = () => {
setNumber(2);
console.log(number);
console.log(mapper[number]);
}
const setThird = () => {
setNumber(3);
console.log(number);
console.log(mapper[number]);
}
return (
<div>
<button onClick={() => { setFirst(); }}>One</button>
<button onClick={() => { setSecond() }} >Two</button>
<button onClick={() => { setThird(); }} >Three</button>
</div>
);
}
Expected: On click of setFirst()
, number should be set to 1. On click of setSecond()
, number should be set to 2. On click of setThird()
, number should be set to 3.
What's happening is
On clicking in sequence setFirst() -> setSecond() -> setThird()
in repeating fashion
Output:
1
One
1
One
2
Two
3
Three
1
One
Expected output:
1
One
2
Two
3
Three
1
One
2
Two
Can someone help me with this. I need help in figuring out where the bug is.
As Chris said in comment, setNumber
is an asynchronous function, so its update is not visible right after it is performed.
Moreover, you should know that, at each render, each methods inside the component is "stacked" inside its current closure. Let me elaborate:
button
(assume just the first one). When the button
is rendered, since setFirst
it's linked to it, you can imagine a sort of room being created, in which all the external variables used inside setFirst
are copied. Thus, since setFirst
uses the variables number
and mapper
, a copy of them is created inside this "room";setFirst
, you run setNumber
. This setNumber
it does NOT update the number
inside setFirst
room, but it updates the number
that will be used in the next render phase; This example is to make you understand why, when you click on setSecond
, you get logged 1 One : when the setSecond
method was initialized for that render, number
was still 1
.
When setter function in eventloop. there is a asynchronous function. You can let be a sync
function. but mostly we are not recommanded do this, so i prefer using callback to do this.
setNumber(2, () => {
console.log('');
})
Anti-Pattern The sync way
Promise.resolve().then(() => {
setNumber(2);
console.log(2);
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.