useTransition은 특정 상태 업데이트를 "급하지 않음(transition)"으로 표시해, 그 렌더 중에도 입력 같은 긴급한 업데이트가 먼저 처리되게 하는 훅이다. [isPending, startTransition]을 반환한다.
const [isPending, startTransition] = useTransition()
const onChange = e => {
setKeyword(e.target.value) // 긴급: 입력창은 즉시
startTransition(() => {
setQuery(e.target.value) // 비긴급: 무거운 목록은 나중에
})
}setTimeout과 다르다. 콜백은 즉시 실행되고, 그 안의 업데이트가 낮은 우선순위로 분류될 뿐이다. 렌더 도중 새 입력이 오면 진행 중인 transition 렌더를 버리고 입력부터 처리한다(동시성 렌더링)- 계산을 빠르게 해 주지 않는다. 500ms 걸리던 렌더는 여전히 그만큼 걸린다. 목적은 그동안 UI가 굳지 않게 하는 것이다
isPending으로 기존 화면을 흐리게 두거나 스피너를 보여 준다. 이미 보이는 내용을 fallback으로 갈아엎지 않는 것도 transition의 효과다(Suspense)- 기준: 사용자가 즉각 반응을 기대하는 상태(입력값, 눌린 탭 표시)는 일반 업데이트로, 그 결과로 따라오는 무거운 UI(검색 결과, 탭 내용)는 transition으로 둔다
- 로딩 상태 수동 관리의 대체물로만 보면 안 된다.
setLoading(true); await f(); setLoading(false)대신 쓰면 짧아지는 게 아니라 업데이트의 의미(우선순위·중단 가능성)가 달라진다 - React 19부터
startTransition에 async 함수를 넘길 수 있다. 요청과 그에 따른 상태 갱신을 하나의 transition으로 묶는 Actions 패턴이며, 폼 쪽은 useActionState와 폼 액션로 이어진다
setState를 직접 감쌀 수 없고 값만 받는 상황이면 useDeferredValue를 쓴다.