QuestionsReact

useTransition & useDeferredValue

Concurrent RenderingHardReact

A search input filters a large list and typing feels laggy. How do React 18's concurrent features fix this, and what's the difference between useTransition and useDeferredValue?

What it tests

Understanding priority-based rendering: keeping urgent updates responsive while deprioritising expensive ones.

Approach & answer

The lag comes from one render doing two things at once: updating the input (urgent — the user must see their keystroke immediately) and re-rendering a huge filtered list (expensive — can lag behind). Before concurrent rendering, both happened in one synchronous, non-interruptible pass, so the keystroke waited on the list. Concurrent rendering lets React mark the expensive update as low-priority and *interruptible* — it can pause the list render to process the next keystroke, then resume or restart. useTransition gives you `[isPending, startTransition]`: wrap the state update that triggers the expensive render in startTransition, and React keeps the input responsive while rendering the list in the background; isPending lets you show a subtle spinner. useDeferredValue is the same idea from the consumer side: you pass a value and get back a version that 'lags behind' during urgent updates — useful when you don't own the state setter (e.g. a value from props or context). Rule of thumb: useTransition when you control the update that causes the work; useDeferredValue when you only have the value. Neither makes the render faster — they make it *non-blocking*, so perceived responsiveness improves. Still memoize the expensive list (React.memo) so deferring actually skips work.

Use this technique when

An urgent update (typing) is blocked by an expensive re-render → mark the expensive update low-priority via startTransition / useDeferredValue.

References

jsx