Search

useTransition

useTransition()useDeferredValue()와 함께 리액트 18버전 이상부터 도입된 동시성 모드(Concurrent Mode)에서 제공하는 훅입니다. 여기서 동시성 모드란 리액트가 작업들을 무조건 순차적으로 처리하는 것이 아닌 각 작업의 우선순위를 배분해 동시다발적으로 처리하는 개념입니다. useTransition()을 사용하면 이 동시성 모드의 이점을 살려 특정 작업의 처리 순서를 지연시켜 다른 작업을 먼저 처리하도록 하여 렉과 같은 현상을 줄여 앱의 사용자 경험(UX)를 향상시킬 수 있습니다.
useMemo(), useCallback()과 같이 앱의 성능을 최적화 하는 용도로 사용되는 훅입니다. 남용해서 사용하는 경우 작업에 불필요한 오버해드가 추가되므로 적절한 경우에만 사용하도록 합시다.

useTransition의 사용

const [isPending, startTransition] = useTransition();
JavaScript
복사
첫번째로 현재 처리 중인지 여부를 알려주는 isPending 플래그를 반환합니다. 처리 중이 아닐 때의 기본 값은 false 입니다.
두번째로 상태 변경의 처리 우선순위를 지연하도록 마크 할 수 있는 startTransition()을 반환합니다. 마크된 상태 변경 함수는 아직 처리 중인 상태일 때 isPending 플래그가 true가 됩니다.
startTransition()은 굉장히 무거운 작업을 처리하는 상태변경 함수(useState()를 사용해 생성한 상태의 set 함수)를 아래처럼 startTransition()로 마크해 주는 식으로 사용합니다. 이렇게 마크된 상태변경 함수는 처리 우선순위가 낮춰지고 작업이 완료되기 전까지 리액트는 다른 작업들을 동시적으로 처리하게 됩니다.
const handler = () => { startTransition(() => { setSomeState( longList.filter(/* 매우 복잡한 작업... */).map(/* 매우 복잡한 작업 2... */) ); }); }; useEffect(() => { console.log(isPending); // setSomeState의 아직 처리 중일 때 true, 처리되었을 때 false }, [isPending]);
JavaScript
복사
예를 들어 아래 코드처럼 사용자가 input 입력 창에 값을 입력할 때마다 setList()가 매우 무거운 작업을 처리하는 경우, useTransition()과 같은 훅으로 처리 우선순위를 지연해 주지 않는다면 setValue()도 함께 지연되어 화면의 input 입력은 렉 현상이 발생하게 됩니다.
const [value, setValue] = useState(''); const [list, setList] = useState([]); const onChange = (e) => { setValue(e.target.value); setList( longList.filter(/* 매우 복잡한 작업... */).map(/* 매우 복잡한 작업 2... */) ); }; return ( <> <input value={value} onChange={onChange} /> {list.map(v => <p>{v}</p>)} </> );
JavaScript
복사
이를 useTransition()을 사용해 아래처럼 수정할 수 있습니다. setList()가 무거운 작업을 처리하는 중이더라도 setValue()는 동시적으로 처리되기 때문에 input의 입력 렉 현상이 발생하지 않습니다. isPending 플래그를 사용해 setList()가 지연 중일 때 로딩 중 텍스트를 표시합니다.
const [value, setValue] = useState(''); const [list, setList] = useState([]); const [isPending, startTransition] = useTransition(); const onChange = (e) => { setValue(e.target.value); startTransition(() => { setList( longList.filter(/* 매우 복잡한 작업... */).map(/* 매우 복잡한 작업 2... */) ); }); }; return ( <> <input value={value} onChange={onChange} /> {isPending ? <p>loading...</p> : list.map(v => <p>{v}</p>)} </> );
JavaScript
복사
만약 isPending의 사용이 필요하지 않고 startTrasition()만 사용해 set 작업의 우선순위를 낮추는 것만 필요한 상황이라면 useTransition()을 호출할 필요 없이 startTransition() 함수만 리액트로 부터 가져와서 바로 사용하는 것도 가능합니다.
import { startTransition } from 'react'; function Component() { // ... const onChange = (e) => { setValue(e.target.value); startTransition(() => { setList( longList.filter(/* 매우 복잡한 작업... */).map(/* 매우 복잡한 작업 2... */) ); }); }; // ... }
JavaScript
복사

 useCallback

 useDeferedValue

React Hooks 목록