const [isPending, startTransition] = useTransition();
startTransition(() => setTab('posts'));
const deferredQuery = useDeferredValue(query);
<SlowList query={deferredQuery} />
Both mark some rendering as non-urgent, so the UI stays responsive. They use concurrent rendering: React can interrupt a non-urgent render when an urgent update, such as typing, arrives.
useTransition returns [isPending, startTransition]. You wrap a state update in startTransition. This makes it a transition, a non-urgent update. React keeps showing the current UI while the new one renders in the background. isPending tells you to show a hint, like a faded tab. Use it when you control the state update, like switching tabs. You cannot use it to update a controlled text input's value.
useDeferredValue(value) gives you a copy of a value that lags behind. React first re-renders with the old value. Then it tries to render with the new value in the background. Use it when you receive the value and cannot wrap its setter. For example, defer a slow results list while the search input stays instant.
- Both hooks mark work as non-urgent and interruptible.
useTransitionwraps a state update and gives youisPending.useDeferredValuedefers a value you receive.- Urgent updates like typing stay responsive.
- Do not use transitions to update a controlled input's value.