Suggest an editImprove this articleRefine the answer for “What does useDeferredValue() do”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)`useDeferredValue(value)` returns a **"deferred version" of a value**, so React can avoid immediately passing the new value into heavy parts of the UI, keeping the interface responsive. **Key point:** typing reacts instantly, while the "expensive" render catches up a little later.Shown above the full answer for quick recall.Answer (EN)Image## What `useDeferredValue()` does `useDeferredValue(value)` returns a "deferred version" of a value. If `value` changes often (for example, while typing in an input), React may **not immediately** propagate the new value into heavy parts of the UI (lists, charts), so the interface stays responsive. The input reacts instantly, while the "expensive" render catches up a little later. A mini example: ```javascript const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); // a "slow" copy // The heavy list filters by deferredQuery, not by the instant query const filtered = useMemo(() => heavyFilter(items, deferredQuery), [items, deferredQuery]); ``` While the user types, `query` changes right away (the input does not lag), while `deferredQuery` updates a little later - the heavy render does not "jerk" on every character. --- ## How `useDeferredValue()` is similar to debounce Both techniques **smooth out** frequent changes, so heavy work does not get triggered too often. The similarity: - They lower the frequency of "expensive" recalculations/renders on fast input. - The user sees a smooth UI with no lag. --- ## How `useDeferredValue()` differs from debounce The main differences are in level and semantics: | Criterion | `useDeferredValue()` | Debounce (for example, `debounce(fn, 300)`) | | --- | --- | --- | | Where it works | Inside React, understands priorities, integrated with Concurrent Rendering | Outside React (a timing utility), "blindly" delays calls | | What it defers | **Propagating a value** to consumers; the render can be interrupted/resumed | **Calling a function** on a timer after a pause | | Delay control | Dynamic, no hard timer; React decides itself when to "catch up" | A fixed interval (for example, 300 ms) | | Cancellation/interruption | Yes: the render can be interrupted if a more important update arrives | Yes: the timer resets on new input, but with no knowledge of React's priorities | | SSR/hydration/concurrency | Naturally compatible | Not integrated at all | | Typical use cases | Decoupling "fast" input from "heavy" UI | Network/handlers, throttling call frequency, autocomplete APIs | In short: **debounce is about time**, `useDeferredValue` **is about render priority**. --- ## How `useDeferredValue()` differs from `startTransition()` Both mechanisms serve "non-urgent" updates, but they apply at different points: | Criterion | `useDeferredValue(value)` | `startTransition(() => setState(...))` | | --- | --- | --- | | Level | **A value**: gives back a "slow" copy of a frequently changing value | **An operation/update**: marks **specific setState calls** as low priority | | Who initiates it | The consumer of the value chooses the "slow" version | You yourself mark a piece of updates as a transition | | Status control | No built-in `isPending` | You get `isPending` via `useTransition()` | | Granularity | Passive: any place that uses the deferred value will "catch up" later | Active: you explicitly wrap "heavy" updates in a transition | | Typical use cases | Heavy memoized computations/lists that depend on a fast-changing `value` | Navigation, filtering, requests, large-scale tree rebuilds | | Asynchrony (React 19+) | Not about async | `startTransition` can be `await`-ed (waiting for async work) | In short: - `useDeferredValue` - "give me a version of this value that can update later". - `startTransition` - "make these *state updates* low priority". --- ## When to choose which - **A heavy list/chart reacts to fast input** → start with `useDeferredValue(query)`. Simple and almost no code. - **You need to mark a batch of updates as "non-urgent" and show an "updating" status** → `const [isPending, startTransition] = useTransition(); startTransition(() => setState(...))`. - **Limit the frequency of network calls / input handlers** → **debounce** (network layer/utilities). You can combine them: debounce for the request, `useDeferredValue` for the heavy UI. --- ## Common patterns **Combo "input + deferred filtering":** ```javascript const [query, setQuery] = useState(''); const deferred = useDeferredValue(query); const list = useMemo(() => heavyFilter(items, deferred), [items, deferred]); ``` **Mark a rebuild as a transition (with an indicator):** ```javascript const [isPending, startTransition] = useTransition(); const onTabChange = (tab: string) => { startTransition(() => setActiveTab(tab)); // a large rebuild of the children }; return <> <Tabs onChange={onTabChange} /> {isPending && <Skeleton />} <HeavyPane tab={activeTab} /> </>; ``` **Debounce only for the request:** ```javascript const debouncedFetch = useMemo(() => debounce(fetchUsers, 300), []); useEffect(() => { debouncedFetch(query); }, [query, debouncedFetch]); ``` (and in parallel you can use `useDeferredValue(query)` for a "smooth" UI) --- ## Summary - `useDeferredValue` - a deferred version of a **value**. About priority, not a timer. - Debounce - a **timer**: it defers **function calls** after a pause. - `startTransition` - marking **state updates** as low priority, with `isPending` and (in React 19+) `await`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.