Concurrency in React 18

How React 18 introduced interruptible rendering with useTransition and useDeferredValue to keep your app responsive during heavy updates.

React6 min readConcept 35 of 46

The Synchronous Rendering Problem

Before React 18, rendering was entirely synchronous. Once React started rendering an update (like setting state), it could not stop until it was finished. It blocked the browser's main thread.

If you typed into a search input, and that search input triggered a heavy data visualization that took 500ms to render, your browser would freeze for 500ms. You couldn't even type the next letter.

React 18 introduced **Concurrent Rendering**. React can now pause a heavy render, handle an urgent user event (like typing or clicking), and then resume the heavy render later.

Urgent vs Non-Urgent Updates

Concurrency introduces the concept of priority. Not all state updates are equally important.

**Urgent updates** reflect direct interaction, like typing, clicking, or dragging. Users expect these to be instant. If they aren't, the app feels broken.

**Non-urgent updates** (Transitions) transition the UI from one view to another, like filtering a massive list or switching pages. Users are okay with a slight delay here, as long as the app doesn't completely freeze.

useTransition and useDeferredValue

React provides two main hooks to opt-in to concurrent features:

const [isPending, startTransition] = useTransition();

Wrap a non-urgent state update inside startTransition. React will process it in the background, keeping the main thread free. The isPending boolean lets you show a loading indicator.

Alternatively, use const deferredQuery = useDeferredValue(query);. This tells React to use the old value for a heavy component until the new value is ready to be rendered in the background.

The Main Thread Scheduler

Compare what happens when a user types into an input field that also triggers a massive UI re-render. In Sync mode, the main thread is blocked. In Concurrent mode, the work is yielded, keeping the input fast.

Interactive Diagram: The Main Thread Scheduler

Sync vs Concurrent Rendering

...
Browser Main ThreadTime ➔
Waiting for input...

In Synchronous mode, a heavy render is one giant block. The browser cannot handle new typing events, paint frames, or do anything else until it finishes. The app feels broken.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What happens in React 17 (synchronous rendering) when a state update takes 500ms to render?
  2. 2When should you use `startTransition`?
  3. 3How does React 18 achieve Concurrent Rendering?

Remember this

  • Before React 18, all rendering was synchronous and un-interruptible.
  • Concurrent rendering allows React to pause heavy renders to handle urgent user events (like typing).
  • Use startTransition to mark a state update as non-urgent.
  • Use useDeferredValue to defer updating a value passed into a heavy component.
  • Concurrency is cooperative scheduling on the main thread, not multi-threading.

Done with this concept?

Mark it complete to track your progress. No login needed.