Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why setState in setTimeout not batching?

Code:

  useEffect(() => {
    setTimeout(() => {
      // this cause re-render twice
      setCount((prev) => prev + 1);
      setCount((prev) => prev + 1);
    }, 1000);
  }, []);

My question is why this component re-render twice if we call two setCount in sequence.
Doesn't React batch multiple setCount in one go?
Thank you for answering or any suggestion.

codesandbox example

like image 791
roy fang Avatar asked Sep 01 '25 20:09

roy fang


2 Answers

EDIT (2023): React 18 has changed this behavior and now even this case will be batched.

Original answer (2020):


Doesn't React batch multiple setCount in one go?

It does if it can. This is a case where it can not.

In order for react to batch things, the execution of code needs to start within react itself. For example, any component lifecycle events, or any synthetic event callbacks (eg, the onClick for a <button>). When that happens, react can let your code keep running, queuing up as many set states as you like, and then once your done you will return to react's code, which can then render the queued changes.

But if code execution did not start from react, then once you return, you're not going to be returning to react's code. So since they won't get to run code after yours, they do the render right away.

like image 81
Nicholas Tower Avatar answered Sep 04 '25 04:09

Nicholas Tower


The other answers explained why it is rendering several times.

Now, I want to give a solution to make it render only once. There is an API that allows you to make only one render: ReactDOM.unstable_batchedUpdates

In your example:

ReactDOM.unstable_batchedUpdates(() => {
    setCount((prev) => prev + 1);
    setCount((prev) => prev + 1);
  });
}, 1000);
like image 26
fjplaurr Avatar answered Sep 04 '25 04:09

fjplaurr