--- id: wiki-2026-0508-starttransition title: startTransition category: 10_Wiki/Topics status: verified canonical_id: self aliases: [startTransition, useTransition, React transition] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [react, concurrent, startTransition, useTransition, priority] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: react-19 --- # startTransition ## 매 한 줄 > **"매 React 18+ 의 update priority API — non-urgent state update 매 mark"**. 매 input typing (urgent) 와 search result render (non-urgent) 의 분리. 매 stale UI 표시, interruptible re-render, Suspense fallback skip 매 가능. 매 useDeferredValue 와 함께 React Concurrent Mode 의 핵심. ## 매 핵심 ### 매 priority 분류 - **Urgent (synchronous)**: 매 input value, click 의 visual feedback. 매 default. - **Transition (low-priority)**: 매 expensive list filter, route change, data 의 UI update. - 매 urgent update 가 transition 중 들어오면 매 transition interrupt + restart. ### 매 useTransition vs startTransition - `useTransition()`: 매 component 안 — `[isPending, startTransition]` 반환. 매 pending UI 표시 가능. - `startTransition(fn)`: 매 import 직접 — pending state 추적 불필요한 case. ### 매 동작 - 매 transition 안 setState 매 low-priority 로 mark. - 매 React 매 다른 urgent work 우선 처리, 매 transition 매 idle 시 처리. - 매 concurrent renderer 매 stale tree 유지하면서 new tree 백그라운드 build. - 매 Suspense — 매 transition 의 fallback 표시 skip (existing UI 유지). ### 매 응용 1. Search input — typing (urgent) + result list (transition). 2. Tab switch — instant feedback + heavy content (transition). 3. Route change — 매 fallback skip 으로 smooth navigation. 4. Filter / sort — 매 list 가 매우 클 때. 5. Data fetch + render — 매 Suspense + transition 조합. ## 💻 패턴 ### useTransition — search ```tsx function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isPending, startTransition] = useTransition(); const onChange = (e: ChangeEvent) => { setQuery(e.target.value); // 매 urgent — input 즉시 update startTransition(() => { setResults(filterItems(e.target.value)); // 매 low-priority }); }; return ( <> {isPending && } ); } ``` ### Tab switch — instant + heavy content ```tsx function Tabs() { const [tab, setTab] = useState<'home' | 'reports' | 'settings'>('home'); const [isPending, startTransition] = useTransition(); const select = (next: typeof tab) => { startTransition(() => setTab(next)); }; return ( <> select('home')} active={tab === 'home'}>Home select('reports')} active={tab === 'reports'}>Reports {isPending && Loading...} {tab === 'home' && } {tab === 'reports' && } ); } // 매 click 의 visual feedback 즉시, content 매 transition. ``` ### useDeferredValue — alternative ```tsx function Search({ query }: { query: string }) { const deferred = useDeferredValue(query); const isStale = deferred !== query; return (
); } // 매 useDeferredValue: 매 prop / state 에서 derive — startTransition 보다 declarative. ``` ### Suspense — fallback skip during transition ```tsx function App() { const [page, setPage] = useState(0); const [isPending, startTransition] = useTransition(); return ( }> {isPending && } {/* 매 suspends on data fetch */} ); } // 매 transition 의 page change 시 매 Skeleton X — 기존 page UI 유지 + spinner. ``` ### React 19 — useTransition 의 async support ```tsx function SaveButton() { const [isPending, startTransition] = useTransition(); const [error, setError] = useState(null); const save = () => { startTransition(async () => { // 매 React 19 부터 async function 직접 지원 try { await api.save(formData); } catch (e) { setError(String(e)); } }); }; return ( ); } // 매 React 18 매 async 직접 X — startTransition 의 outer wrap 필요. ``` ### Route change — Next.js App Router ```tsx 'use client'; import { useRouter } from 'next/navigation'; import { useTransition } from 'react'; function Nav() { const router = useRouter(); const [isPending, startTransition] = useTransition(); return ( ); } ``` ### Combined with flushSync (반대 우선순위) ```tsx // 매 startTransition: 매 low-priority, batchable, interruptible. startTransition(() => setBigList(newData)); // 매 flushSync: 매 high-priority, sync, immediate. flushSync(() => setUrgent(true)); // 매 둘은 정반대 — 매 같이 사용 X. ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Heavy filter / sort with input | useTransition. | | Tab / route switch | useTransition. | | Derived value from prop | useDeferredValue. | | Async save / submit (React 19+) | useTransition (async). | | Imperative DOM after state | flushSync (반대). | | Simple fast state | 매 plain setState. | **기본값**: 매 user input 분리 의 concurrent UI — useTransition. 매 prop-derived expensive 은 useDeferredValue. ## 🔗 Graph - 부모: [[React]] · [[Concurrent React]] - 변형: [[useTransition]] · [[useDeferredValue]] · [[Suspense]] - 응용: [[Search]] - Adjacent: [[flushSync]] · [[Automatic Batching]] · [[React Server Components]] ## 🤖 LLM 활용 **언제**: 매 input + heavy filter, tab switch, route change with data fetch, async form submit (React 19+) 의. **언제 X**: 매 simple light state update (overhead 무의미), 매 imperative DOM 의 즉시 sync (flushSync), 매 server-only logic. ## ❌ 안티패턴 - **모든 setState 에 startTransition**: 매 useless overhead, 매 input lag 등 의 unintended effect. - **isPending 무시**: 매 visual feedback 없으면 user confusion. - **External state (zustand etc.) 의 transition**: 매 useTransition 매 React state 만 affect — external store 매 자체 batching. - **Animation 의 transition**: 매 animation 매 urgent — interrupted 되면 jank. flushSync / RAF 사용. - **React 18 의 async startTransition**: 매 React 18 매 sync function 만 — async 매 outer wrap 또는 React 19 upgrade. ## 🧪 검증 / 중복 - Verified (React docs useTransition, React 18 release notes, React 19 changes). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — startTransition / useTransition patterns, useDeferredValue 비교, React 19 async 추가 |