-
useTransition와 useDeferredValue 알아보기Frameworks, Platforms and Libraries/React 2024. 4. 28. 13:59
React 18버전에서 새로 나온 hooks인 useTransition을 이번에 사용하게 되어 팀 내에서도 공유하고 포스팅도 하게 되었습니다. useTransition와 비슷한 역할을 가진 useDeferredValue도 같이 알아보겠습니다.
useTransition?
React 공식 홈페이지에서 useTransition 설명은 다음과 같습니다.
useTransition is a React Hook that lets you update the state without blocking the UI.
useTransition 은 UI를 차단하지 않고 state를 업데이트할 수 있는 React 훅입니다.useTransition은 파라미터를 받지 않고 isPending, startTransition 두 개의 값을 반환합니다. isPending은 트랜지션의 지연 상태를 나타내는 boolean 타입의 flag 값이며 startTransition은 state의 변화를 트랜지션으로 나타내는 함수로 파라미터로 콜백 함수를 받으며 전달받은 함수의 우선순위를 낮춰 지연시키는 함수입니다.
const [isPending, startTransition] = useTransition();
해당 내용만 봐선 useTransition의 이해가 쉽게 와닿지 않아 예시를 통해 살펴보겠습니다.
import { ChangeEvent, useEffect, useState } from 'react'; import './App.css'; function App() { const [count, setCount] = useState<number>(0); const [countArr, setCountArr] = useState<number[]>([]); const updateCount = () => { const arr = Array(100000) .fill(0) .map((_, i) => count * i); setCountArr(arr); }; useEffect(() => { updateCount(); }, [count]); return ( <> <h1>React Hooks Test</h1> <div className="section"> <input type="number" value={count} onChange={(e: ChangeEvent<HTMLInputElement>) => setCount(Number(e.currentTarget.value)) } /> <div className="box"> {countArr.map((val, idx) => ( <span key={idx}>{val}</span> ))} </div> </div> </> ); } export default App;
실제 개발 시 나오지 않을 코드이지만 state의 극단적인 변화를 보이기 위해 작성된 코드입니다. 해당 코드의 결과는 아래와 같습니다.
updateCount의 무거운 로직으로 인해 state의 setting이 늦어지며 이에 따라 UI의 끊김 현상을 살펴볼 수 있습니다.
useTransition을 사용하여 위의 코드를 개선해 보겠습니다.
import { ChangeEvent, useEffect, useState, useTransition } from 'react'; import './App.css'; function App() { const [count, setCount] = useState<number>(0); const [countArr, setCountArr] = useState<number[]>([]); const [isPending, startTransition] = useTransition(); const updateCount = () => { startTransition(() => { const arr = Array(100000) .fill(0) .map((_, i) => count * i); setCountArr(arr); }); }; useEffect(() => { updateCount(); }, [count]); return ( <> <h1>React Hooks Test</h1> <div className="section"> <input type="number" value={count} onChange={(e: ChangeEvent<HTMLInputElement>) => setCount(Number(e.currentTarget.value)) } /> {isPending && <div className="load-box">loading...</div>} {!isPending && ( <div className="box"> {countArr.map((val, idx) => ( <span key={idx}>{val}</span> ))} </div> )} </div> </> ); } export default App;
startTransition을 통해 updateCount 실행의 우선순위를 낮추고 이에 따른 트랜지션 상태를 isPending을 통해 판단하여 조건부 렌더링을 걸어두었습니다.
결국 useTransition은 startTransition을 통해 함수 실행의 우선순위를 늦출 수 있으며 이에 따른 지연 상태를 isPending으로 나타냅니다. useTransition을 이용한 UI를 사용자에게 제공 시 더 나은 UX를 가지게 합니다.
useDeferredValue?
useTransition과 함께 React 18버전에서 나온 useDeferredValue에 대해 알아보겠습니다. 우선 공식 문서에서 설명은 아래와 같습니다.
useDeferredValue is a React Hook that lets you defer updating a part of the UI.
useDeferredValue는 UI 일부의 업데이트를 지연시킬 수 있는 React 훅입니다.useDeferredValue은 파라미터로 모든 타입의 값을 받을 수 있으며 파라미터로 전달받은 값을 그대로 반환하지만 지연된 버전의 값으로 반환합니다.
const deferredValue = useDeferredValue(value)
위의 내용만 봐선 useDeferredValue의 이해가 쉽지 않지만 useTransition과 비슷한 내용이 많이 보입니다. useDeferredValue도 예시를 통해 살펴보겠습니다.
import { useDeferredValue, useState } from 'react'; import './App.css'; function App() { const [first, setFirst] = useState<number>(0); const [second, setSecond] = useState<number>(0); const deferredValue = useDeferredValue(second); const updateNumber = () => { setFirst((f) => f + 1); setSecond((s) => s + 1); }; console.log('first', first); console.log('second', second); console.log('deferredValue', deferredValue); return ( <> <h1>React Hooks Test</h1> <div className="section"> <button onClick={() => updateNumber()}>button</button> </div> </> ); } export default App;
useDeferredValue을 사용하여 선언된 deferredValue의 값의 변화가 다른 state의 변화가 끝난 뒤에 발생되었음을 알 수 있습니다.
결론
useTransition과 useDeferredValue는 state의 변화에 대한 우선순위를 낮추는 hook이라는 공통점을 가지며 useDeferredValue는 state 값 자체에 우선순위를 낮추지만 useTransition는 state 변화를 일으키는 함수에 우선순위를 낮추는 차이점을 가집니다.
마무리
React의 버전이 업데이트될수록 다양한 기능이 나오고 있습니다. React의 버전을 업데이트할 때 새로운 기능을 파악하여 적재적소에 맞게 사용해야겠습니다.
참고 자료
https://react-ko.dev/reference/react/useTransition
https://react-ko.dev/reference/react/useDeferredValue
https://dev.to/sameer1612/react-v18-usetransition-hook-why-3bml
'Frameworks, Platforms and Libraries > React' 카테고리의 다른 글
String to HTML, dangerouslySetInnerHTML (0) 2024.06.09 Recoil 도입기 (0) 2024.05.19 useEffect dependency에 useRef를 담기보단 Callback Refs를... (0) 2024.02.25 React Query Key Factory (0) 2023.11.25 React Query 도입기 (0) 2023.11.09