본문 바로가기

useDefferedValue 본문

React

useDefferedValue

개발자로 거듭나기 2023. 10. 3. 16:00
반응형

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;

출처

https://react-ko.dev/reference/react/useDeferredValue

반응형

'React' 카테고리의 다른 글

React 배너 슬라이더 만들기 + touch evnet  (3) 2024.01.04
useTransition  (0) 2023.10.03
RTK Query 캐쉬 무효화  (0) 2023.10.03
Comments