I suppose this is because how JS works, but you wouldn't have this problem with classes I suppose. In this code:
let [open, setOpen] = React.useState(false);
let [counter, setCounter] = React.useState(0);
function handleClick() {
setOpen(true);
setInterval(() => {
console.log(counter);
setCounter(counter + 1);
}, 2000);
}
If I call handleClick once (e.g. click button), the value logged on console is always 0 (despite state being updated each time).
This is probably because of the closure. But what if I wanted to see the most recent value of counter
in such setup?
With classes you could have done this.state.counter
and it would read latest value.
Is there some workaround with hooks?
demo.
Note: I found this question which asks basically the same. Somehow I didn't encounter it on initial search.
setState , and React. useState create queues for React core to update the state object of a React component. So the process to update React state is asynchronous for performance reasons. That's why changes don't feel immediate.
The setInterval() method repeats a given function at every given time-interval. window. setInterval(function, milliseconds); The window.
setInterval is a method that calls a function or runs some code after specific intervals of time, as specified through the second parameter. For example, the code below schedules an interval to print the phrase: “Interval triggered” every second to the console until it is cleared.
Check the next example, refer to setState
in react docs.
export default function SimpleSnackbar() {
const classes = useStyles();
let [open, setOpen] = React.useState(false);
let [, setCounter] = React.useState(0);
// Save reference for clearing the interval
// in your case you firing an interval on every click
const lastInterval = useRef();
// Side effect on `open` change.
useEffect(() => {
if (lastInterval.current) clearInterval(lastInterval.current);
if (open) {
lastInterval.current = setInterval(() => {
// Functional setState
setCounter(prevCounterValue => {
console.log(prevCounterValue);
return prevCounterValue + 1;
});
}, 1000);
}
}, [open]);
function handleClick() {
setOpen(true);
}
function handleClose(event, reason) {
if (reason === 'clickaway') {
return;
}
setOpen(false);
}
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With