useTransition & Responsive UI

useTransition is a React Hook that lets you mark certain state updates as non-urgent "transitions," so React can keep the interface responsive — like a typing cursor — while a heavier update such as re-rendering a large list happens in the background. It returns an isPending flag and a startTransition function you wrap around the slow update.

Learn useTransition & Responsive UI in our free React course — an interactive lesson with runnable examples, a practice exercise and a quick recall.

Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

1️⃣ Urgent vs Non-Urgent Updates

A single keystroke can trigger two updates: showing the typed character (must be instant) and filtering a huge list against it (can lag a few milliseconds). By default React treats both as urgent and does them together, so typing stutters. The fix is to tell React which update can wait.

2️⃣ startTransition — Mark the Heavy Update

Call const [isPending, startTransition] = useTransition() . Keep the urgent setQuery outside, and wrap the heavy setList in startTransition(...) . React now renders the input immediately and processes the list at a lower priority it can interrupt.

3️⃣ isPending — Showing Progress

While the transition's render is in flight, isPending is true . Use it to dim stale results or show a tiny spinner, signalling that fresher output is coming — all without freezing the input. Compared to debouncing (which simply delays starting the work), a transition starts now but stays interruptible.

These lines form a responsive search handler. Put them in the right order:

📋 Quick Reference

1. Which update goes inside startTransition — the input or the list?

The heavy list update. The input's setQuery stays outside so it remains urgent and instant.

2. Does useTransition make the list render faster?

No. It changes priority, not raw speed. The list takes the same time, but typing stays smooth because React can interrupt the render.

It's true while the transition is rendering, so you can show a spinner or dim stale results.

Model the handler that fires the urgent log first, then a transition that flips a pending flag around the heavy work. Run it and check your output.

Practice quiz

What does useTransition return?

  • A single boolean value
  • A ref object

useTransition returns [isPending, startTransition] — a flag that's true while the transition renders, and a function to mark updates as non-urgent.

What does wrapping a state update in startTransition do?

  • Marks the update as non-urgent so React can interrupt it for urgent work
  • Makes the update run faster
  • Delays the update by a fixed timeout
  • Cancels the update entirely

Answer: Marks the update as non-urgent so React can interrupt it for urgent work. startTransition marks the enclosed updates as transitions (non-urgent), so React can keep urgent updates like typing responsive.

In a search box, which update should stay OUTSIDE startTransition?

  • The heavy list-filtering update
  • Both should go inside
  • Neither matters
  • The urgent controlled-input update (setQuery)

Answer: The urgent controlled-input update (setQuery). Keep setQuery outside so the input stays instant. Only the heavy setList goes inside the transition, where it can be deprioritized.

Does useTransition make your slow rendering code actually faster?

  • Yes, it speeds up the render itself
  • No — it reorders priority, not raw speed
  • Yes, by caching the result
  • Only if the list is sorted

Answer: No — it reorders priority, not raw speed. The heavy work still takes the same time. useTransition just lets React interrupt it for urgent updates so typing stays smooth.

What is isPending used for?

  • To show a spinner or dim stale results while the transition renders
  • To cancel the transition
  • To measure the DOM
  • To store the previous value

Answer: To show a spinner or dim stale results while the transition renders. isPending is true while a transition's render is in progress, letting you signal that fresher output is coming without blocking input.

How does a transition differ from debouncing?

  • They are identical techniques
  • A transition always waits 300ms first
  • Debounce delays when work starts; a transition starts now but stays interruptible
  • Debouncing keeps the UI interactive but transitions block it

Answer: Debounce delays when work starts; a transition starts now but stays interruptible. Debounce postpones starting the work; a transition begins immediately at low priority and lets React interrupt it for urgent input.

What kind of updates does the classic startTransition expect inside it?

  • Asynchronous awaited work
  • Synchronous state updates
  • DOM measurements
  • Network requests only

Answer: Synchronous state updates. Classic startTransition expects synchronous state updates inside its callback. Awaited async work uses different transition patterns.

Why might typing feel janky WITHOUT useTransition when filtering a large list?

  • React refuses to update inputs
  • The input element is disabled
  • useState batches forever
  • Both the input and heavy list updates are urgent and done together, blocking the input

Answer: Both the input and heavy list updates are urgent and done together, blocking the input. By default React treats both updates as urgent and processes them together, so the heavy list render blocks the input and typing stutters.

To actually reduce the work a transition is doing, what should you pair it with?

  • Nothing — transitions reduce work on their own
  • Memoization like useMemo or React.memo
  • A longer secondsPerQuestion
  • useLayoutEffect

Answer: Memoization like useMemo or React.memo. Transitions reorder priority, not raw cost. Pair them with useMemo / React.memo to cut the actual rendering work.

Which is a true statement about useTransition?

  • It only works in class components
  • It must be called inside an event handler
  • It is a React 18 concurrent feature for marking non-urgent updates
  • It replaces useState entirely

Answer: It is a React 18 concurrent feature for marking non-urgent updates. useTransition is a concurrent feature added in React 18; you call it at the top level like other Hooks and use startTransition to mark non-urgent updates.