useDeferredValue

useDeferredValue is a React Hook that returns a deferred copy of a value, allowing an expensive part of your UI to lag a moment behind a fast-changing input so the input stays responsive while heavy results catch up. You give it a value and React gives you back a version that updates at a lower priority.

Learn useDeferredValue 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️⃣ The Idea: A Value That Catches Up

Call const deferred = useDeferredValue(value) . The live value updates immediately (great for the input), while deferred may briefly hold the previous value during a busy render, then catch up. Pass deferred — not value — to the heavy part.

2️⃣ Pair It With React.memo

Deferring only helps if the expensive child can skip re-rendering when its prop hasn't changed. Wrap that child in React.memo and feed it the deferred value. Now it re-renders only when the deferred value updates — not on every keystroke — which is where the smoothness comes from.

3️⃣ Showing Staleness & vs useTransition

When , a newer render is pending — dim the list to signal "catching up." The key difference from useTransition : a transition wraps the code that triggers the update (you own the setState ), while useDeferredValue wraps a value you already have — perfect when the value is a prop you can't control.

These lines build a smooth search box. Put them in the right order:

📋 Quick Reference

1. Which value do you pass to the expensive child?

The deferred value. The live value goes to the input; the lagging deferred value goes to the heavy results.

So the child skips re-rendering while the deferred prop is unchanged. Without memo it re-renders every keystroke and the lag buys you nothing.

3. useTransition vs useDeferredValue — pick one in a sentence.

Use a transition when you own the setState ; use a deferred value when you only have a value (often a prop) flowing in.

Model an expensive filter that only recomputes when the query actually changes, the way a deferred value plus memo behaves. Run it and check your output.

Practice quiz

What does useDeferredValue return?

  • A debounced callback
  • A memoized component
  • A deferred copy of a value that updates at a lower priority, lagging behind during busy renders
  • A boolean indicating loading

Answer: A deferred copy of a value that updates at a lower priority, lagging behind during busy renders. You pass it a value and get back a version that may briefly hold the previous value during a busy render, then catch up.

Which value do you pass to the expensive child component?

  • The deferred value
  • The live value
  • Both, alternating
  • Neither; you pass a ref

Answer: The deferred value. The live value goes to the fast input; the lagging deferred value goes to the heavy results so they update a beat later.

Why does useDeferredValue pair with React.memo?

  • memo is required by the hook
  • memo makes the value update faster
  • It prevents memory leaks
  • So the expensive child can skip re-rendering when its deferred prop is unchanged instead of re-rendering every keystroke

Answer: So the expensive child can skip re-rendering when its deferred prop is unchanged instead of re-rendering every keystroke. Deferring only helps if the child can skip work. Wrapping it in React.memo means it re-renders only when the deferred value actually changes.

How do you detect that results are stale (a newer render is pending)?

  • Check a loading boolean
  • Compare the live and deferred values: value !== deferredValue means it's catching up
  • Use a setTimeout
  • Read a ref count

Answer: Compare the live and deferred values: value !== deferredValue means it's catching up. When the live value differs from the deferred one, a fresher render hasn't landed yet — a common pattern is dimming the list while they differ.

Does useDeferredValue debounce with a fixed delay?

  • No — it's not a timer; the lag adapts to how busy React is
  • Yes, 300ms by default
  • Yes, but configurable
  • Only in production

Answer: No — it's not a timer; the lag adapts to how busy React is. It lets the deferred value lag during a busy render and catch up when React has spare time. For a fixed wait you'd still use a debounce.

How does useDeferredValue differ from useTransition?

  • They are identical
  • useTransition only works on the server
  • A transition wraps the code that triggers the update (you own the setState); useDeferredValue wraps a value you already have
  • useDeferredValue requires Suspense

Answer: A transition wraps the code that triggers the update (you own the setState); useDeferredValue wraps a value you already have. Use a transition when you own the setState. Use a deferred value when you only have a value flowing in — often a prop you can't control.

What's the bug if you pass the live value (not the deferred one) to the heavy child?

  • Nothing changes
  • Nothing is deferred — the expensive child still updates on every keystroke
  • The input stops working
  • React throws an error

Answer: Nothing is deferred — the expensive child still updates on every keystroke. Deferring requires feeding the deferred value to the expensive component; passing the live value defeats the entire optimization.

How would you dim stale results in JSX?

  • <div hidden={isStale}>
  • <div disabled>
  • <div className="loading">
  • <div style={{ opacity: isStale ? 0.5 : 1 }}>

Answer: <div style={{ opacity: isStale ? 0.5 : 1 }}>. A common pattern sets opacity to 0.5 while value !== deferred, visually signaling that fresher results are on the way.

When is useDeferredValue a better fit than useTransition?

  • When you want a fixed delay
  • When the slow input is a value (often a prop) you can't wrap the setState for
  • When you have no expensive child
  • When rendering on the server

Answer: When the slow input is a value (often a prop) you can't wrap the setState for. If you only have a value flowing in and can't control where its setState happens, deferring that value is the right tool.

Besides React.memo, what helps avoid recomputing an expensive filter each render?

  • useCallback on the child
  • useRef for the result
  • useMemo keyed on the deferred value
  • Nothing is needed

Answer: useMemo keyed on the deferred value. Wrapping the expensive computation in useMemo keyed on the deferred value avoids recomputing it on unrelated renders.