5

I'm curious about why setting state in a for loop doesn't work as expected.

This is my code using hooks.

const [count, setCount] = useState(0);

  const onButtonPress = () => {
    for(let i=0; i<100; i++){
      setCount(i);
    }
  }

  useEffect(()=> {
    console.log('useEffect called');
    console.log(count);
  },[count])

I call the onButtonPress function on a button click.

Behavior I expect: count state shoukd update 100 times and consequently call the useEffect hook a 100 times.

Actual behavior: The useEffect hook is being only called once after the last iteration of the loop.

I know that the official react docs say that hooks shouldn't be used in loops but their explanation isn't very clear.

I want to understand why calling setCount in a loop doesn't work.

NOTE: I know that there are other methods to achieve the desired result but I'm interested in understanding why the setCount wouldn't be called multiple times.

Rohan Bhatia
  • 61
  • 1
  • 3

2 Answers2

6

state updates are batched by react, so if you call the same state updater many times in your handler, the entire operation will be batched and a single update will be performed which is what you witness

Also when the docs say that the hooks shouldn't be used within loops they mean by hooks such as useState, useRef, useEffect and so on and not the state updater being returned by useState hook

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
3

React dispatches the state changes in batch, when running a for loop it quickly batches 100 requests resulting in only 1 state update and eventually 1 re-render. If you use setTimeout event with 0ms, you'd able to get the required but I'm not totally sure about your use-case.

Muhammad Ali
  • 2,538
  • 2
  • 16
  • 21
  • setTimeout does help my use case. Thanks for that. Why doesn't react batch the state changes when we use setTimeout with 0ms? – Rohan Bhatia May 20 '20 at 14:18
  • setTimeout is async callback given by browser, it gets out of javascript's call stack and gets injected into callback queue, this whole process is something called event loop. Please watch this [video](https://www.youtube.com/watch?v=8aGhZQkoFbQ), you can thank me later :p – Muhammad Ali May 20 '20 at 14:37