Search

useDeferredValue

useDeferredValue()useTransition()과 함께 리액트 18버전 이상의 동시성 모드(Concurrent Mode)에서 제공하는 훅으로, 특정 값의 처리 우선순위를 낮추어 렉 현상을 줄여 사용자경험(UX)을 향상시키는 목적으로 사용됩니다.
useTransition()과 차이점이라면 useTransition()useCallback()처럼 특정 함수를 마킹하여 처리 우선순위를 낮추지만 useDeferredValue()useMemo()처럼 특정 값을 마킹하여 우선순위를 낮추는 식으로 사용합니다.
useMemo(), useCallback()과 같이 앱의 성능을 최적화 하는 용도로 사용되는 훅입니다. 남용해서 사용하는 경우 작업에 불필요한 오버해드가 추가되므로 적절한 경우에만 사용하도록 합시다.

useDeferredValue의 사용

const [state, setState] = useState(''); const deferredState = useDeferredValue(state);
JavaScript
복사
useDeferredValue()는 보통 useState() 훅과 함께 사용합니다. useState()로 생성된 state 값을 인자로 사용하여 상태 업데이트의 처리 우선순위를 낮추고 다른 작업을 동시적으로 처리하도록 허용합니다. 위 코드처럼 useDeferredValue()로 마킹된 state는 상태 업데이트(setState())가 오래 걸리더라도 다른 작업을 지연 시키거나 렉 현상을 발생시키지 않게끔 다른 작업을 먼저 우선해서 처리하도록 합니다. deferred value라는 뜻 그대로, 값 변경이 일어날 때 다른 작업을 우선 처리하도록 해서 지연된 결과 값을 사용하게 되는 것이죠.
useMemo()와 같이 사용할 때 좋은 시너지를 보여줍니다. 예를 들어 아래 코드처럼 input의 value 값이 바뀔 때마다 키워드를 검색하여 List를 새로 만들어주는 로직이 있을 때, List의 불필요한 리랜더링을 막기 위해 보통 useMemo()로 래핑하여 사용합니다.
const [value, setValue] = useState(''); const onChange = (e) => { setValue(e.target.value); }; const List = useMemo(() => { // 아래 로직은 비교적 무거운 로직은 아니지만, longList가 매우 길어 처리 시간이 오래 걸리는 작업이라 가정 const list = longList.filter(item => item.includes(value)); return list.map(v => <li>{v}</li>); }, [value]); return ( <> <input onChange={onChange} /> <ul> {List} </ul> </> );
JavaScript
복사
위 코드로는 유저가 매우 빠르게 input에 타이핑을 할 경우 useMemo()로 래핑한 List이긴 하지만 하더라도 value 값이 매우 빠르게 바뀌므로 매번 복잡한 로직을 처리할 때마다 다른 작업 처리도 함께 늦어지는 렉 현상이 발생하게 됩니다.
이 때 value 대신 useDeferredValue()로 래핑된 값을 사용하는 것으로 변경하면 사용자가 빠른 속도로 타이핑하여 value를 빠르게 변경 하더라도 deferredValue가 지연 처리되어 변경되기 때문에 useMemo()로 래핑한 List도 덜 반복적으로 생성되고 다른 작업을 우선 처리 함으로써 화면 렉 발생을 줄여주게 됩니다.
const [value, setValue] = useState(''); // useDeferredValue으로 래핑하여 지연된 value 값 생성 const deferredValue = useDeferredValue(value); const onChange = (e) => { setValue(e.target.value); }; // deferredValue가 작업 우선순위가 낮으므로 List의 생성도 비교적 덜 반복적으로 수행됨 const List = useMemo(() => { const list = longList.filter(item => item.includes(deferredValue)); return list.map(v => <li>{v}</li>); }, [deferredValue]); return ( <> <input onChange={onChange} /> <ul> {List} </ul> </> );
JavaScript
복사

 useTransition

React Hooks 목록