← Back to the journal
ReactFrontendPerformance

React 18: concurrent and smooth

React 18 brings concurrent rendering, automatic batching and transitions — what that means for genuinely smooth user interfaces.

React 18 has just landed, and it's one of those releases you only really understand once you build with it. At first glance little changes — most apps simply keep running. At second glance, how React thinks about time has shifted.

Concurrent rendering

The foundation is the concurrent architecture. React can now interrupt, pause and resume rendering instead of pushing an update through in one uninterruptible pass. That means an expensive update no longer necessarily blocks what's more urgent right now — like typing or clicking.

Smoothness doesn't come from everything being faster, but from the important thing coming first.

You feel this through startTransition. With it I mark an update as non-urgent — say, filtering a long list — while the input itself stays instantly responsive. The interface remains live, even when a lot is happening underneath.

What changes day to day

Two smaller additions I particularly like, because they just feel frictionless:

  • Automatic batching now also groups state updates inside promises, timeouts and native events into a single re-render — fewer wasted passes, with no effort from me.
  • useTransition and useDeferredValue give me fine control over what's allowed to wait.

Adoption is gentle: with createRoot I switch on the new capabilities, and a lot simply works better without rewriting code. The genuinely interesting patterns then arrive gradually.

For me, React 18 isn't a loud update. It's one that shifts responsibility: instead of juggling when things render myself, I just tell React what has priority — and let it handle the timing. That's exactly what makes interfaces smooth without anyone seeing the machinery.