--- id: wiki-2026-0508-usedeferredvalue title: useDeferredValue category: 10_Wiki/Topics status: verified canonical_id: self aliases: [React useDeferredValue, Deferred Rendering, Stale-While-Revalidate Hook] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [react, hook, concurrent, performance, react-19] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: React 19 --- # useDeferredValue ## 매 한 줄 > **"매 useDeferredValue 의 핵심 = 'value 의 stale copy 의 keep 의 background 의 update'."**. React 18 (2022) 의 introduction 의 since 매 useTransition 의 sibling — but 매 ownership 의 invert: 매 value 의 you don't control (props / context). 2026 React 19 era 매 third-party state 의 (TanStack Query data, Zustand store) 의 smooth 의 render. ## 매 핵심 ### 매 Signature ```typescript const deferredValue = useDeferredValue(value, initialValue?); // initialValue (R19+): 매 first render 의 fallback ``` ### 매 Mechanism - 매 first render: deferredValue === value (or initialValue if 의 provided). - 매 subsequent re-render with new value: 1. React 의 first re-render 의 with old deferredValue (urgent, cached). 2. Background 의 re-render 의 with new value (interruptible). 3. 매 commit 의 newer one 의 ready when. - **isStale check**: `value !== deferredValue` → 매 pending state 의 indicate. ### 매 vs useTransition 1. **Ownership**: useTransition 의 setter 의 own. useDeferredValue 의 value 의 from outside. 2. **Use case**: useTransition for 의 own state. useDeferredValue for 의 props / library state. 3. 매 둘 다 의 same scheduler 의 use. ## 💻 패턴 ### Pattern 1: Slow-rendering child 의 with prop value ```typescript import { useDeferredValue, memo } from 'react'; function SearchPage({ query }: { query: string }) { const deferredQuery = useDeferredValue(query); const isStale = query !== deferredQuery; return (
); } const SearchResults = memo(function SearchResults({ query }: { query: string }) { // Expensive: filter 100k items const items = expensiveFilter(query); return ; }); ``` ### Pattern 2: TanStack Query 의 smooth pagination ```typescript import { useQuery } from '@tanstack/react-query'; import { useDeferredValue } from 'react'; function ProductList({ page }: { page: number }) { const deferredPage = useDeferredValue(page); const { data } = useQuery({ queryKey: ['products', deferredPage], queryFn: () => fetchProducts(deferredPage), }); const isStale = page !== deferredPage; return (
{data?.map(p => )}
); } ``` ### Pattern 3: React 19 initialValue (avoid first-render flash) ```typescript function Chart({ data }: { data: DataPoint[] }) { // initialValue: 의 first render 의 empty 의 use, then 의 background 의 real data const deferredData = useDeferredValue(data, []); return ; } ``` ### Pattern 4: Combine 의 useTransition (own state) + useDeferredValue (derived) ```typescript function App() { const [filter, setFilter] = useState(''); const [isPending, startTransition] = useTransition(); return ( <> startTransition(() => setFilter(e.target.value))} /> ); } // Inside library / external component 의 ChildList 의 only props 의 receive function ChildList({ filter }: { filter: string }) { const deferred = useDeferredValue(filter); return ; } ``` ### Pattern 5: Stale indicator with useDeferredValue ```typescript function Autocomplete({ input }: { input: string }) { const deferredInput = useDeferredValue(input); const suggestions = computeSuggestions(deferredInput); const isStale = input !== deferredInput; return (
    {suggestions.map(s =>
  • {s}
  • )} {isStale &&
  • Updating...
  • }
); } ``` ### Pattern 6: With memo 의 critical ```typescript // memo() 의 X → useDeferredValue 의 useless (re-render every time anyway) const Heavy = memo(function Heavy({ value }: { value: string }) { // Expensive render return ; }); function Parent({ live }: { live: string }) { const deferred = useDeferredValue(live); return ; // memo 의 only re-render when 'value' prop changes } ``` ### Pattern 7: Server Component data 의 defer (RSC + Suspense) ```typescript 'use client'; import { useDeferredValue, use, Suspense } from 'react'; function ClientWrapper({ promise }: { promise: Promise }) { const deferredPromise = useDeferredValue(promise); return ( }> ); } function Resolved({ promise }: { promise: Promise }) { const data = use(promise); // R19 use() hook return ; } ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Expensive render of incoming prop | useDeferredValue + memo | | Library state (TanStack Query, etc.) | useDeferredValue | | 매 own state setter | useTransition | | Throttle / debounce input value | lodash.debounce — useDeferredValue 의 X | | First-render empty placeholder | useDeferredValue with initialValue (R19) | **기본값**: useDeferredValue + memoized child whenever 의 prop change 의 trigger 의 expensive render. ## 🔗 Graph - 부모: [[Concurrent-React]] - 변형: [[useTransition]] - Adjacent: [[memo]] · [[Suspense]] ## 🤖 LLM 활용 **언제**: identify 의 candidate prop 의 deferral / suggest 의 memo wrapping / migrate 의 throttle 의 useDeferredValue. **언제 X**: 매 measurement 의 X — 매 Profiler 의 first. ## ❌ 안티패턴 - **No memo on child**: 매 deferred value 의 effect 의 X → child 의 every parent render 의 re-render. - **Use as throttle**: 매 rate limiting 의 X — 매 latest value 의 always 의 catch up. - **Defer urgent values**: search input 의 own value 의 defer → input 의 lag. - **Forget isStale UX**: 매 user feedback 의 없이 → 매 perceived bug. - **Defer non-expensive value**: 매 simple string render 의 defer → 의 unnecessary complexity. ## 🧪 검증 / 중복 - Verified: react.dev/reference/react/useDeferredValue (React 19), React 19 release notes. - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — canonical useDeferredValue reference (React 19) |