C.W.K.
Stream
Lesson 02 of 06 · published

useDeferredValue — 무거운 렌더 lag

~11 min · usedeferredvalue, concurrent, rendering

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
useDeferredValue 가 값 받아서 '늦은' 버전 줌. Input 은 긴급 유지. 비싼 렌더가 늦은 버전 읽고 살짝 lag. 결과: 타이핑이 즉시 느껴짐; 결과가 catch up.

모양

const deferred = useDeferredValue(value). deferred 가 초기엔 value 와 같음, 그 다음 고우선순위 렌더 (타이핑) 중엔 이전 값과 같음 — 새 값으로의 새 렌더가 백그라운드에서 진행 중. 백그라운드 렌더 완료 시 deferred 업데이트, 무거운 subtree 가 새 값으로 re-render.

useDeferredValue vs useTransition

둘 다 비슷한 UX 달성. 차이: 값을 누가 소유.

  • useTransition — 본인이 state 소유, 업데이트를 startTransition 으로 감쌈.
  • useDeferredValue — 값이 본인이 제어 안 하는 곳에서 (prop, context). 업데이트 감쌀 수 없지만 값을 deferrable 로 표시 가능.

본인 제어 컴포넌트 안: useTransition. Prop 받음: useDeferredValue.

React.memo 와 짝

useDeferredValue 가 비싼 자식이 prop 안 바뀌었을 때 re-render 스킵 가능할 때만 도움. 자식을 React.memo 로 감싸 (또는 Compiler 가 memoize 신뢰). Memoization 없으면 deferred 값이 여전히 매번 re-render 트리거, 이득 잃음.

데이터 말고 렌더 defer. 데이터는 이미 있음; React 가 언제 paint 할지 본인이 선택. useDeferredValue 가 'input 업데이트 지금 렌더, 비싼 subtree 는 할 수 있을 때'. 스케줄링, throttle 아님.

Code

Memoized 무거운 자식과 useDeferredValue·tsx
import { memo, useDeferredValue, useState } from "react";

function SearchPage() {
  const [query, setQuery] = useState("");
  // Deferred 가 query 에 lag — 타이핑 즉시 유지.
  const deferredQuery = useDeferredValue(query);
  const isStale = query !== deferredQuery;

  return (
    <div>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <div style={{ opacity: isStale ? 0.6 : 1 }}>
        <Results query={deferredQuery} />
      </div>
    </div>
  );
}

const Results = memo(function Results({ query }: { query: string }) {
  // 비싼 렌더 — memo 가 query 안 바뀌었으면 스킵.
  // useDeferredValue 와 함께 input 보다 덜 자주 re-render.
  return <ul>{filterLargeList(query).map((r) => <li key={r}>{r}</li>)}</ul>;
});

function filterLargeList(_q: string): string[] { return []; }

External links

Exercise

Lesson 1 의 검색 연습을 useTransition 대신 useDeferredValue 쓰게 리팩토링. 결과 컴포넌트를 React.memo 로 감쌈. Input 이 반응 유지하고 결과가 살짝 lag 하는지 확인. 그 다음 memo 제거하고 useDeferredValue 단독으론 안 도움 — input 업데이트와 비싼 렌더가 매 키스트로크마다 발화 — 관찰.
Hint
memo + useDeferredValue 가 캐논 짝. memo 없으면 deferred 값이 여전히 매 render 마다 fresh prop 받음, 목적 좌절.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.