React Holiday

#9: Opt in to automatic batching with createRoot

When we update to the new root API (createRoot), we get performance improvements out-of-the-box.

Neat!

Automatic batching is a performance improvement that reduces useState re-renders. Imagine an event handler that updates two pieces of state, count and isOdd.

function handleClick() {
  updateCount((count) => count + 1);
  updateIsOdd((isOdd) => !isOdd);
  // only one re-render
}

These state updates are batched and result in one re-render. But that changes if we call those updater functions outside of this function (think asynchronous fetch).

When we call updater functions outside of handler functions, we lose batching. Look at this slight alteration below where we wrap updater functions in a setTimeout.

These updates will not be batched.

function handleClick() {
setTimeout(() =>
updateCount(count => count + 1);
updateIsOdd(isOdd => !isOdd);
, 0)
// one re-render per update
}

This is both a permormance issue and and expectation problem.

Fortunately, React 18 fixes this. Now, useState updater functions are automatically batched — no matter where they are called.

🐦 chantastic

P.S.
Because React 18 automatically batches all updates, you can safely remove unstable_batchedUpdates. With the new root API, this function is a no-op.