Hey code wizards! 🧙‍♂️
Remember the old days when you’d update two state variables in a row, and React would re-render your component twice? Yeah, that was annoying. It was like ordering a burger, the waiter running to the kitchen, then coming back to ask for your drink order, and running back again. Exhausting, right?
Well, React 18 introduced something called Automatic Batching, and it’s basically a smarter waiter.
Let’s dive in and see how this magic works.
The Problem: Too Many Re-renders
In React 17 and older, React only “batched” state updates if they happened inside a browser event (like a click). If you did it inside a setTimeout or a fetch callback, React would panic and re-render for every single state update.
Here is a classic example of the “bad old days”:
// React 17 behavior inside a timeout
setTimeout(() => {
setCount(c => c + 1); // Re-render 1
setFlag(f => !f); // Re-render 2
}, 1000);
If you had a heavy component, this double rendering could make your UI feel sluggish. Not cool.
The Solution: Automatic Batching
React 18 is smarter. It says, “Hey, I see you’re updating multiple things. I’m gonna wait a split second, collect all your changes, and then update the DOM just once.”
It doesn’t matter where you trigger the updates:
- Event handlers? Batched.
- Promises? Batched.
- Timeouts? Batched.
Check this out:
import { useState } from 'react';
function BatchingExample() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
// React 18 will batch these automatically!
// It doesn't matter if it's in a promise or timeout.
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render ONCE at the end of this!
}, 1000);
}
console.log("Render!"); // This logs only once per click in React 18
return (
<div>
<button onClick={handleClick}>Click Me</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
This is a huge performance win out of the box. You don’t have to change your code; just upgrading to React 18 gives you this superpower.
Opting Out (If You Really Need To)
Sometimes, very rarely, you might want to force a re-render immediately after a state update. Maybe you need to read the DOM right away (though usually, a useEffect is better for that).
You can use flushSync from react-dom to tell React: “Do this NOW.”
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setCount(c => c + 1);
});
// React has updated the DOM here
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM again here
}
But seriously, don’t use this unless you have a very specific reason. Let React do its thing.
Wrapping Up
Automatic Batching is one of those features that makes you love React even more. It’s fewer re-renders, better performance, and less code for us to worry about.
So, go ahead and update your states fearlessly! React has got your back.
Happy coding! 🚀