Concurrent rendering: transitions, deferred values and tearing
Keep input responsive while a slow part of the UI updates: urgent vs transition updates, useTransition and startTransition, useDeferredValue, isPending, interrupted renders, and how useSyncExternalStore prevents tearing.
Comes up in: React, Frontend system design
Learn#
Ishita’s product search filters 5,000 items on every keystroke. Typing lags by half a second, because each letter waits for the whole list to render.
Concurrent rendering lets React prepare a render in the background and interrupt it. You mark which updates can wait. Urgent updates, such as typing, clicking and pressing, render at once. A transition is a non-urgent update that can be interrupted.
const [isPending, startTransition] = useTransition();
function onTabClick(tab) {
startTransition(() => setTab(tab)); // can be interrupted
}When you do not own the state update, such as a prop, use a deferred value: const deferredQuery = useDeferredValue(query). The input uses query; the slow list uses deferredQuery, which lags behind.
Page
- <input value="s">
State
empty
The user types "s". setQuery('s') is urgent: the input re-renders at once.
Read the steps as text
- The user types "s". setQuery('s') is urgent: the input re-renders at once.
- The filtered list uses useDeferredValue(query). React starts a background render of 5,000 rows for "s".
- The user types "h" before it finishes. React drops the unfinished "s" render and handles the keystroke first.
- With typing paused, the "sh" list render completes and commits. Meanwhile the old list stayed visible, dimmed with isPending.
Predict#
Predict first
You wrap setQuery (bound to a controlled input) in startTransition. What happens when the user types?
A controlled input must update urgently, or it shows stale text. Keep the input’s state urgent and defer the expensive part, with a second state in a transition or with useDeferredValue. Wrapping everything in a transition is a common first mistake.
Interview angle#
Say it like this — about 30 seconds
“Transitions mark updates as non-urgent. With useTransition or startTransition, React renders them in the background, interrupts them for urgent input, and throws away renders that are already stale. isPending lets me show the old UI dimmed instead of a spinner. useDeferredValue does the same for a value I receive. Tearing is when parts of the UI show different versions of external state during a concurrent render; useSyncExternalStore prevents it by reading a consistent snapshot.”
Follow-up What are transitions in React? When would you use useTransition?
Follow-up What is tearing, and how does useSyncExternalStore prevent it?
Follow-up Does a transition make the slow render faster?
Practice#
On your own
Build a small external store that works correctly with useSyncExternalStore.
Done when
getSnapshotreturns the same object until the state changes.- Subscribers are notified after each real change, and can unsubscribe.
- Updates that return the same object do nothing.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
What does startTransition do?
Marks updates as non-urgent so React can interrupt them for urgent input.
When do you use useDeferredValue instead of useTransition?
When you get the value as a prop and do not own the state update.
What is tearing?
Parts of the UI showing different versions of the same external state.
Why must getSnapshot return a cached object?
A new object each call looks like a change, so React re-renders forever.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
isPending is true while a transition renders. Show the old content with lower opacity instead of a spinner, so the page does not jump.Check yourself: What does isPending tell you?
A transition is still rendering in the background.
How it works underneathSenior rounds
Check yourself: What happens to a transition render that becomes outdated?
React throws it away and starts again with the latest state.
Edge cases and trapsWhere people slip
useSyncExternalStore(subscribe, getSnapshot) detects that and re-renders synchronously with one consistent snapshot Source: React: useSyncExternalStore.Check yourself: Why did external stores tear in concurrent rendering?
The store could change between slices of a render, so components read different values.
In productionStaff-level answers
Use transitions for navigation, tabs and heavy filtering; routers in React 19 frameworks wrap navigations in transitions for you. Measure with the Profiler and INP (QLT.01.03) before and after.
Check yourself: Which interactions are good candidates for transitions?
Tab switches, filtering large lists, and route navigation.
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- What are transitions in React? When would you use
useTransition? - What is tearing and how does
useSyncExternalStoreprevent it?