8

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.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90

1 Answers1

3

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);
  }

  ...
}

Edit Material demo

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • ah I know functional `setState`, didn't know hooks had it too. But why not such simple answer:https://codesandbox.io/s/material-demo-of22b? This would satisfy my question already. – Giorgi Moniava Sep 12 '19 at 10:29
  • As I mentioned, on every click you will set an interval, when do you clear it? Also, you can clear it within `handleClose`, your choice. – Dennis Vash Sep 12 '19 at 10:30
  • Ah ok, but that was an existing material demo, I jumped on, in reality I am not interested in that dialog opening, etc. Just the question about `setInterval`.. – Giorgi Moniava Sep 12 '19 at 10:31