Blog
Changes in the React 18 Update – Part #2

Changes in the React 18 Update – Part #2

React 18 and the Automatic batching.

14 de outubro de 2021

To check out part #1 of this article, click here!

React 18

Hi everyone! In this second episode of React 18, I’ll discuss a very important topic that will help understand one of the things React does to work, and that directly affects performance and execution sequence.

I’m referring to Automatic batching.

But what on earth is Automatic batching?

Batching is when React prepares several state updates, forming a group that will be executed in a single render, which in turn generates a performance gain in your application.

When you change a variable through setState inside a function or callback, React doesn’t execute them one by one. Instead, it prepares what we know as Batching (batch) and executes all setStates together.

const App = () => {
  const [amountCookies, setAmountCookies] = useState(0);
  const [isOdd, setIsOdd] = useState(false);

  const handleEatCookies = useCallback(() => {
    setAmountCookies(oldState => ++oldState);// Doesn’t render, but is added to the batch.
    setIsOdd(oldState => !oldState);// Doesn’t render, but is added to the batch.
    //React renders the batch states once!
  }, [setIsOdd, setAmountCookies]};

  return (<br/><div><br/><h1 style={{ color: isOdd? “blue” : “red” }}>{count} Cookies eaten!</h1><br/><button onClick={handleEatCookies }>Eat a Cookie</button><br/></div><br/>   );
}

And what’s new in all this?

To understand what’s new, we need to clarify what’s old. We understand that batching is great for performance because it avoids unnecessary renders.

However, this only happened in DOM event handlers. Therefore, Promises, timeouts or other handlers didn’t take advantage of it.

const handleEatCookies = useCallback(() => {
Promise.resolve().then(() => {
setAmountCookies(oldState => ++oldState);// Renders.
setIsOdd(oldState => !oldState);// Renders.
});
}, [setIsOdd, setAmountCookies]};
const handleEatCookies = useCallback(() => {
setTimeout(() => {
setAmountCookies(oldState => ++oldState);// Renders.
setIsOdd(oldState => !oldState);// Renders.
}, 10000);
}, [setIsOdd, setAmountCookies]};

React 18 will send state updates in batches, regardless of where they happen.

That is: Promises, timeouts and others will benefit from batching, as long as it is safe to do so. This results in better performance, without any additional involvement.

I need my function to render more than once, what do I do?

Currently, if we want our states to render before a function finishes, we can do a trick like this:

const handleEatCookies = useCallback(() => {
function resolveAmount(){
setAmountCookies(oldState => ++oldState);// Renders.
};
resolveAmount();
setIsOdd(oldState => !oldState);// Doesn’t render, but is added to the batch.
//React renders the batch states once!
}, [setIsOdd, setAmountCookies]};

And with React 18, we get a function from ReactDOM, called flushSync, which serves to create the batching that renders after its declaration.

import { flushSync } from “react-dom”;
//…
const handleEatCookies = useCallback(() => {
flushSync(() => {
setAmountCookies(oldState => ++oldState);// Doesn’t render, but is added to the batch
});
//React renders the batch states above!
flushSync(() => {
setIsOdd(oldState => !oldState);// Doesn’t render, but is added to the batch.
});
//React renders the batch states above!
}, [setIsOdd, setAmountCookies]};
//…

The expansion of automatic batching to other levels and types of functions will make it easier for us to create more performant applications, and flushSync will provide an elegant way to deviate from the pattern when needed.

If you have any questions or want to know more about something I mentioned in this article, or just to say what you thought, don’t hesitate to write in the comments, it will be very important for me to bring relevant content.

Thank you very much for reading this far and see you in the next chapter.

Tadeu Agostini

This article was developed by Tadeu Agostini, front-end Web developer at Zappts.