useDefferedValue 본문
반응형
useDefferedValue
개념 및 사용법
useDeferredValue
는 UI 일부의 업데이트를 지연시킬 수 있는 React 훅입니다.- 컴포넌트의 최상위 레벨에서
useDeferredValue
를 호출하여 지연된 버전의 값을 가져옵니다.
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
// query: 지연시키려는 값입니다. 어떤 타입이든 가질 수 있습니다.
// defferdQuery : 초기 렌더링 중에는, 반환된 ‘지연된 값’은 사용자가 제공한 값과 동일합니다.
// 업데이트가 발생하면 React는 먼저 이전 값으로 리렌더링을 시도(반환값이 이전 값과 일치하도록)하고,
// 그 다음 백그라운드에서 다시 새 값으로 리렌더링을 시도(반환값이 업데이트된 새 값과 일치하도록)합니다.
const deferredQuery = useDeferredValue(query);
// ...
}
주의사항
useDeferredValue
에 전달하는 값은 문자열 및 숫자와 같은 원시값이거나, 컴포넌트의 외부에서 생성된 객체여야 합니다. 렌더링 중에 새 객체를 생성하고 즉시useDeferredValue
에 전달하면 렌더링할 때마다 값이 달라져 불필요한 백그라운드 리렌더링이 발생할 수 있습니다.useDeferredValue
가 현재 렌더링(여전히 이전 값을 사용하는 경우) 외에 다른 값([Object.is](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
와 비교)을 받으면 백그라운드에서 새 값으로 다시 렌더링하도록 예약합니다. 값에 대한 또 다른 업데이트가 있으면 백그라운드 리렌더링은 중단될 수 있습니다. React는 백그라운드 리렌더링을 처음부터 다시 시작할 것입니다. 예를 들어, 차트가 리렌더링 가능한 지연된 값을 받는 속도보다 사용자가 input에 값을 입력하는 속도가 더 빠른 경우, 차트는 사용자가 입력을 멈춘 후에만 다시 렌더링됩니다.useDeferredValue
는<Suspense>
와 통합됩니다. 새 값으로 인한 백그라운드 업데이트로 인해 UI가 일시 중단되면 사용자에게 폴백이 표시되지 않습니다. 데이터가 로드될 때까지 기존의 지연된 값이 계속 표시됩니다. (useTransition을 이용해서 transition을 사용하는 경우에도 Suspense를 이용한 fallback이 표시되지 않음)useDeferredValue
는 그 자체로 추가 네트워크 요청을 방지하지 않습니다.useDeferredValue
로 인한 백그라운드 리렌더링은 화면에 커밋될 때까지 Effect를 실행하지 않습니다. 백그라운드 리렌더링이 일시 중단되면 데이터가 로드되고 UI가 업데이트된 후에 해당 Effect가 실행됩니다.
사용법
- 초기 렌더링 시점에 지연된 값은 사용자가 제공한 값(value)과 동일합니다.
- 업데이트가 발생하면, 지연된 값은 최신 값보다 “뒤쳐지게” 됩니다. React는 먼저 지연된 값을 업데이트하지 않은 채로 렌더링한 다음, 백그라운드에서 새로 받은 값으로 다시 렌더링을 시도합니다.
- deferredText 가 아닌 그냥 text를 넘기고 결과를 비교해보세요.
- 이 최적화를 위해서는
SlowList
를[memo]
로 감싸야 합니다. 텍스트가 변경될 때마다 React가 부모 컴포넌트를 빠르게 다시 렌더링할 수 있어야 하기 때문입니다. 다시 렌더링하는 동안deferredText
는 여전히 이전 값을 가지므로SlowList
는 리렌더링을 건너뛸 수 있습니다(props는 변경되지 않았습니다).[memo]
가 없다면 어쨌든 다시 렌더링해야 하므로 최적화의 취지가 무색해집니다.
- useDefferdValue.tsx
import SlowList from "@/components/SlowList";
import { useState, useDeferredValue } from "react";
export default function useDefferdValue() {
const [text, setText] = useState("");
const deferredText = useDeferredValue(text);
return (
<>
<input value={text} onChange={(e) => setText(e.target.value)} />
<SlowList text={deferredText} />
</>
);
}
- SlowList.tsx
import { memo } from "react";
const SlowList = memo(function SlowList({ text }: { text: string }) {
console.log("[ARTIFICIALLY SLOW] Rendering 250 <SlowItem />");
let items = [];
for (let i = 0; i < 250; i++) {
items.push(<SlowItem key={i} text={text} />);
}
return <ul className="items">{items}</ul>;
});
function SlowItem({ text }: { text: string }) {
let startTime = performance.now();
while (performance.now() - startTime < 1) {}
return <li className="item">Text: {text}</li>;
}
export default SlowList;
출처
반응형
'React' 카테고리의 다른 글
React 배너 슬라이더 만들기 + touch evnet (3) | 2024.01.04 |
---|---|
useTransition (0) | 2023.10.03 |
RTK Query 캐쉬 무효화 (0) | 2023.10.03 |
Comments