DEV Community

vatana7
vatana7

Posted on

Ever wonder why React's setState doesn't update immediately?

Yesterday I was browsing new React's website react.dev that includes up-to-date documentation and tutorials out of boredom. While browsing, I have come across this section called Queueing a Series of State Updates and it sparked an interest in me. After reading, I have learned something new from it.

Now I always knew that React doesn't instantly update state when you tell it you to do so. I always knew this in the back of my head but never really knew what is happening inside the hood.

Here's an example:

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

  const handleClick = () => {
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  };

// For somebody who just started to learn React you might 
// think that count would be 3 right? Nope
Enter fullscreen mode Exit fullscreen mode

It turns out that React will waits for the codes inside the event handlers to finish before processing your state updates and then re-render. React calls it batching. For an analogy, it's like a waiter is waiting for you to make all your orders then run to the kitchen to give it to the cook.
In React's context, it means React will wait until you call a bunch of setState then group it together and make a single re-render to improve performance. This process is called batching.

So in order to immediately update the state multiple times before next render, you can React's Updater Function.

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

const handleClick = () => {
    setCount(count + 1);
    setCount((count) => count + 1); // called updater function
    // next render count = 2
 };
Enter fullscreen mode Exit fullscreen mode

Here's a psuedocode to demonstrate how React's queue work inside the hood.

let count = 0 //Initial value
const queue = [
setCount(count + 1), // return count = 1
setCount(count => count + 1)  // return count as 1+1 = 2
]
rerender()
Enter fullscreen mode Exit fullscreen mode

So if you want to simultaneously update the state without waiting for the next render you can use Updater Function to make it happen.

In conclusion, today we have learnt that React has an operation called batching that take multiple setState call and wait to execute it at once for improvement. And we also learn how to update state immediately using Updater Function without waiting for next render as well. I hope you learn something new today!

Thank you!

Top comments (5)

Collapse
 
sergo profile image
Sergo

Hey! I don't know, but it's not working.

Collapse
 
vatana7 profile image
vatana7

Hey if you're wondering why, because the counter you have put in console.log() is actually the old state. After calling a bunch of set function, the screen hasn't re-render yet so that's why you're seeing old state on console.log which is 0. To see changes, you need to put useEffect and put a dependency of counter. After that you should see 2.

Pls also remember that

    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
Enter fullscreen mode Exit fullscreen mode

won't give you 3. You have to call an updater function which is setCounter((counter) =>counter + 1); to increment the value one by one

Collapse
 
sergo profile image
Sergo

Hey, thank you for your feedback. I know that we need to use useEffect(), but you didn't write in article about it. So, I decided that it works without useEffect(), but with updater function.

Collapse
 
tristan_m profile image
Tristan M・トリスタン

I only somewhat recently figured out the same thing after browsing the update react docs page out of curiosity and looking for info on making custom Hooks by extracting stateful code outside of our main files.

This ability to take out queuing almost completely removed all of my useEffect queries that was handling tiered levels of state change across 3-4 state variables.

Granted... in hindsight I could've just handled all of my state in a single state object instead of having so many state variables!

Thanks for taking the time to write up and share!

Collapse
 
vatana7 profile image
vatana7

Thank you for your comment!