What does useDeferredValue() do when working with asynchrony?
What useDeferredValue() does
useDeferredValue(value)defers updating a value so React can first render the fast and important parts of the interface, and update the "heavy" or asynchronous parts a bit later.
In other words:
React makes the UI responsive without blocking the rendering of slow components.
A simple explanation
Picture a search field where every keystroke triggers a request to the server:
<input value={query} onChange={e => setQuery(e.target.value)} />
<SearchResults query={query} />The problem:
- the user types fast -
querychanges with every character; - every render triggers filtering or a network request;
- the UI starts to "lag" (stutters while typing).
1. How useDeferredValue solves this
import { useState, useDeferredValue, Suspense } from 'react';
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then(r => r.json());
function SearchResults({ query }) {
const { data } = useSWR(`/api/search?q=${query}`, fetcher, { suspense: true });
return <ul>{data.results.map(r => <li key={r}>{r}</li>)}</ul>;
}
export default function Search() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
<Suspense fallback={<p>Loading...</p>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}What happens:
- The user types fast (
queryupdates instantly). - React does not rush to update the heavy component (
SearchResults) for every character. - It holds back the update of
deferredQueryuntil it becomes "free". - As soon as the user stops actively typing -> React updates
deferredQuery.
As a result:
- the input field stays responsive;
- expensive computations and requests do not block the UI.
2. Behavior in practice
| Event | query | deferredQuery | What React does |
|---|---|---|---|
| The user types "React" | changes fast: R -> Re -> Rea -> ... | lags behind | React renders only the input |
| The user has stopped | catches up with query | loads data for "React" |
3. Difference from startTransition()
| Hook | What it does |
|---|---|
useDeferredValue(value) | defers using a value (the reactive version) |
startTransition(callback) | defers running a state update |
An example of equivalent behavior:
// the startTransition variant
import { startTransition } from 'react';
function onChange(e) {
const value = e.target.value;
setImmediateQuery(value); // update fast (the input)
startTransition(() => setDeferredQuery(value)); // deferred - search
}useDeferredValue() does the same thing, but declaratively:
const deferredQuery = useDeferredValue(query);4. Typical use cases
| Case | What useDeferredValue does |
|---|---|
| Search | defers updating the results list so typing does not lag |
| Large lists | updates the list's render a bit later so the UI stays responsive |
| Suspense data loading | lets you show old data while new data is being loaded |
| Filters / sorting | avoids re-rendering the table on every click |
| Charts and visualization | renders updates only when React is "free" |
5. An example with a heavy visual load
function HeavyList({ filter }) {
const items = Array.from({ length: 5000 }, (_, i) => `Item ${i}`);
const filtered = items.filter(i => i.toLowerCase().includes(filter.toLowerCase()));
return (
<ul>{filtered.map(i => <li key={i}>{i}</li>)}</ul>
);
}
export function Search() {
const [filter, setFilter] = useState('');
const deferredFilter = useDeferredValue(filter);
return (
<>
<input
value={filter}
onChange={e => setFilter(e.target.value)}
placeholder="Filter..."
/>
<HeavyList filter={deferredFilter} />
</>
);
}With fast typing:
- the input field reacts instantly (rendering is "not blocked");
- the list updates with a slight delay (a bit later).
6. How it works "under the hood"
useDeferredValue:
- returns a "lagged copy" of the value;
- marks updates that depend on it as low priority;
- React performs these updates only when the UI is free;
- if a new value arrives while waiting, the old one is discarded.
This is part of React Concurrent Rendering, a mechanism where React itself decides what to update first and what can wait.
SUMMARY
| What it does | Why it is needed |
|---|---|
| Defers updating a value | prevents lags with frequent updates |
| Does not block input and fast updates | the UI stays responsive |
| Lets you work smoothly with Suspense | old data stays on screen |
| Uses low render priority | React makes a "smart" update plan |
| Great for search, filters, lists | reduces unnecessary requests and renders |
In short:
useDeferredValue()is a way to tell React: "Here is a new value, but do not rush to render it - update when there's time."It makes the interface smooth and responsive, especially with asynchronous data loading or rendering heavy components.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.