Skip to content
Journal

Engineering

React 18 in Production: What Actually Changed for Us

Headshot of Alex Fujimoto
Alex Fujimoto
July 12, 2022 · 2 min read

We moved our first client project to React 18 in April, about a month after the stable release, and by now most of our active builds are on it. Enough time has passed to separate the release notes from the reality, so here is our honest accounting.

The upgrade itself was boring, which is a compliment

The React team did serious work to make this a non-event. Swapping ReactDOM.render for createRoot took an afternoon across our largest codebase, and the automatic batching changes surfaced exactly two bugs, both in code that was relying on intermediate render states it should never have relied on.

import { createRoot } from "react-dom/client";

const root = createRoot(document.getElementById("app"));
root.render(<App />);

If your app breaks under React 18, the honest framing is usually that React 18 found a bug you already had.

Concurrent features: useful, narrower than the hype

The marketing story around concurrency suggests everything gets smoother automatically. That is not how it works. Concurrent rendering is opt-in, gated behind features like startTransition and useDeferredValue, and most components will never touch it.

Where it earned its keep for us: search and filter interfaces. On the Northwind product catalog, filtering a few thousand SKUs used to jank visibly on mid-tier Android devices. Wrapping the filter state update in startTransition let keystrokes stay responsive while the list re-render happened at lower priority. Measured input delay dropped from occasionally exceeding 200ms to consistently under 50ms on our test devices. That is a real, user-visible win from about ten lines of code.

Where it did not matter: almost everything else. Marketing pages, forms, checkout flows. If your renders are already fast, deprioritizing them buys nothing.

Suspense and streaming SSR: promising, waiting on frameworks

The new streaming server renderer with selective hydration is the most architecturally interesting part of React 18, and it is also the part we can barely use yet. The primitives exist, but the ergonomics depend on framework support, and the frameworks are still catching up. We are watching what the Next.js team ships next with real interest, because the direction of travel is clear: send HTML earlier, hydrate what the user touches first.

For now, our practical position is that streaming SSR is a 2023 story for client work. We do not build production sites on release candidates.

What we tell clients

A few honest takeaways when the upgrade question comes up in planning:

  • Upgrade for the foundation, not the features. Library support is consolidating around 18, and staying current is cheaper than staying behind.
  • Budget a day or two, not a sprint, for a healthy codebase.
  • Expect one or two concurrency wins in genuinely interactive surfaces, and do not promise more.
  • StrictMode double-mounting in development will annoy your team for a week and then make your effects better forever.

React 18 is a good release precisely because it undersells itself in daily use. The dramatic stuff is infrastructure for what comes next. The immediate value is smaller and steadier: fewer renders, smoother input, and a codebase positioned for wherever the ecosystem lands over the next year.

Building something this could apply to?

We take on a small number of flagship projects each quarter.

Start a project