0

I have been experimenting with setInterval. Both the codes were executed in Chrome. Below is my react component

function App() {
  let [value, setValue] = useState(0);

  useEffect(() => {
    const id = setInterval(() => console.log(value), 1000);

    return () => clearInterval(id);
  }, []);

  return (
    <div className="App">
      <p>{value}</p>

      <button onClick={() => setValue(value + 1)}>+</button>
      <button onClick={() => setValue(value - 1)}>-</button>
    </div>
  );
}

The console.log in setTimeout inside useEffect keeps printing 0 no matter how many times you increment or decrement the value via button click.

Following code is being executed in browser (Chrome) console

let value = 0;

setInterval(() => console.log(value), 1000);

value = 3; // can be considered as setValue (sort of)

Now the browser console prints 3 which is expected.

I wonder why there is a difference in behaviour and would appreciate if someone could point out the reason for this. Any other code snippet or link that demonstrate this even better would be great.

Rishabh Singh
  • 353
  • 2
  • 8
  • and in your second code snippet you are explicitly defining a value within your code block and then reading the result. In the first one, you are trying to the read result of state which is set asynchronously. – Dan Oct 24 '21 at 18:20
  • Does this answer your question? [State not updating when using React state hook within setInterval](https://stackoverflow.com/questions/53024496/state-not-updating-when-using-react-state-hook-within-setinterval) – juliomalves Oct 26 '21 at 21:23

2 Answers2

2

You need to pass value as a dependency to your useEffect. Unless you give the list of items that your effect dependent upon in the dependency array, it will keep using the initial value.

  useEffect(() => {
    const id = setInterval(() => console.log(value), 1000);

    return () => clearInterval(id);
  }, [value]);
Kuncheria
  • 1,182
  • 9
  • 16
  • This will result in the `console.log` happening one second after every click and for every click, which i don't think is what the question is asking for. – Houssam Oct 24 '21 at 17:55
  • @Houssam why would you think that? As far as I can tell this is exactly what the OP wants. – Jared Smith Oct 24 '21 at 18:10
  • That was my understanding from the question and what made me curious about what the explanation is. My understanding is that the `useEffect` triggers the `setInterval`, then the OP clicks on the "+" button within that 1 second timer and expect to see "1" in the console, but see "0" instead. – Houssam Oct 24 '21 at 18:24
  • @Houssam is right. The intention of the code is not to trigger `console.log` after every click. Its just to print the value every 1s irrespective of any clicks. Also if `value` is passed in the dependencies array then everytime `value` changes it would simply recreate the interval with latest value which would of corse work. – Rishabh Singh Oct 25 '21 at 05:09
  • @RishabhSingh did you actually run this code? Because I did and it prints the value of `value` every second, correctly, with every increment and decrement taken into account. Has nothing to do with clicks. – Jared Smith Oct 25 '21 at 16:11
  • @JaredSmith Checkout this sandbox https://codesandbox.io/s/dawn-voice-g5ncs?file=/src/App.js. No matter how many times the button is clicked `console.log` always prints `0`. – Rishabh Singh Oct 25 '21 at 17:29
  • 1
    @RishabhSingh yes, ***again***, just like it says in this (correct) answer, you have to add `value` to the dependency array. *There's even yellow squigglies under that array in the sandbox because the linter is already complaining about it*. – Jared Smith Oct 25 '21 at 17:33
1

İn your example useEffect only work once when page loaded. This is why you only get console.log(0). If you want to make it when value change you need specify that in useEffect

For example

UseEffect(() =>{ console.log(value) }, [value])

In your example when you click to button, first value sets after that useEffect works and setInternals function triggered after 1s.

hasankzl
  • 666
  • 4
  • 16