Back to React
React
medium
mid

Can you explain the concurrent features introduced in React 18?

Concurrent rendering lets React pause/resume/abandon renders. Key features: automatic batching across async boundaries, `startTransition` / `useTransition` for non-urgent updates, `useDeferredValue` for lagging expensive derivations, Suspense for data + lazy components, streaming SSR with selective hydration. The model: urgent updates (input) preempt non-urgent (large list re-renders).

4 min read·~8 min to think through

React 18 introduced concurrent rendering — the scheduler can pause/resume/abandon a render in progress, enabling responsiveness during heavy work.

Automatic batching

Pre-18: multiple state updates inside the same event handler were batched; updates inside setTimeout/Promise weren't.

js
// React 17: two renders. React 18: one render.
setTimeout(() => {
  setA(1);
  setB(2);
}, 0);

startTransition / useTransition

Mark a state update as non-urgent. React can interrupt it for urgent input.

tsx
const [isPending, startTransition] = useTransition();

function onChange(e) {
  setQuery(e.target.value);                       // urgent
  startTransition(() => setResults(filter(...)));  // can be interrupted
}

Input stays snappy; the heavy filter is interruptible if the user types again.

useDeferredValue

For derived values:

tsx
const deferred = useDeferredValue(query);
const list = useMemo(() => filter(items, deferred), [deferred]);

deferred lags during fast typing; React renders the old value first, the new one later.

Suspense improvements

  • Server Components + streaming SSR flush HTML in chunks gated by Suspense.
  • Selective hydration — React hydrates the components the user interacts with first.

Strict Mode

Double-mounts components in dev to surface missing cleanups (effects, subscriptions). Not a perf feature but related to the concurrent model.

Tradeoffs

  • Effects can run twice in dev (Strict Mode).
  • useEffect deps must be precise — the new model exposes stale-closure bugs more often.
  • Some libraries needed updates for compat.

Interview framing

"Concurrent rendering means React's scheduler can pause/abandon a render. The user-facing primitives are automatic batching (across async boundaries), startTransition / useTransition for non-urgent updates so input stays snappy, useDeferredValue for expensive derivations that should lag, and Suspense for data + lazy. Streaming SSR + selective hydration shorten time-to-interactive. The mental shift: not every state update has to render immediately."

Follow-up questions

  • Difference between startTransition and useDeferredValue.
  • What is selective hydration?
  • Why does Strict Mode double-mount in dev?

Common mistakes

  • Treating transitions as throttle.
  • Putting urgent UI updates inside startTransition.
  • Misunderstanding Strict Mode warnings as bugs.

Performance considerations

  • Transitions and deferred values keep INP low under load. Streaming SSR cuts perceived load time.

Edge cases

  • Synchronous flushSync escape hatch.
  • Concurrent rendering + non-concurrent libraries (older state libs).
  • Suspense fallback flickers without proper boundaries.

Real-world examples

  • Next.js App Router, Vercel docs, React 18 release blog.

Senior engineer discussion

Seniors map transitions and deferred values to the right perf problems (network vs render) and design Suspense boundaries deliberately.

Related questions