I have the following code:
function App() {
// array to store 3 numbers, all initialized to 0
const [counter, setCounter] = React.useState<number[]>([0, 0, 0]);
// increments counter[i] by 1
const increment = (i: number) => {
let newCount = [...counter];
newCount[i] += 1;
setCounter(newCount);
}
return (
<div className="App">
<header className="App-header">
<p>
count: {counter[0]} {counter[1]} {counter[2]}
</p>
<button onClick={() => {
[0, 1, 2].map((i) => {
// pretend that setTimeout is making some web request
setTimeout(() => increment(i), 1000);
});
}} >Increment All</button>
</header>
</div>
);
}
When I click on the button, I want it to increment all 3 numbers in the array, but it looks like only the last setTimeout
call will take effect (and thus only one of the values get incremented).
I think I understand why that is (the counter
value is constant within the react onClick
event handler call), but I don't know how best to structure this code to avoid this issue. Do I have to buffer the increments and "commit" the changes all at once via one call to setCounter
? Is there a better way?