The query will update immediately, so the input will display the new value.
However, the deferredQuery will keep its previous value until the data has loaded, so SearchResults will show the stale results for a bit.
렌더링 중 생성한 객체를 useDeferredValue에 전달하면 안 되는 이유는?
렌더링할 때마다 새 객체를 만들면 매번 "다른 값"으로 인식되어 불필요한 백그라운드 렌더링이 계속 발생한다. 문자열이나 숫자 같은 원시 값 또는 렌더링 바깥에서 만든 객체를 전달해야 한다.
The values you pass to useDeferredValue should either be primitive values (like strings and numbers) or objects created outside of rendering.
If you create a new object during rendering and immediately pass it to useDeferredValue,
it will be different on every render, causing unnecessary background re-renders.
useDeferredValue는 백그라운드 리렌더링과 중단을 어떻게 관리하는가?
두 단계로 작동한다. 먼저 새 값이 들어오면 이전 deferred 값으로 빠르게 화면을 그리고, 이어서 백그라운드에서 새 값으로 다시 그린다. 백그라운드 작업이 끝나면 화면에 반영된다.
When useDeferredValue receives a different value (compared with Object.is), in addition to the current render (when it still uses the previous value), it schedules a re-render in the background with the new value.
You can think of it as happening in two steps:
First, React re-renders with the new query ("ab") but with the old deferredQuery (still "a").
The deferredQuery value, which you pass to the result list, is deferred: it “lags behind” the query value.
In the background, React tries to re-render with both query and deferredQuery updated to "ab".
If this re-render completes, React will show it on the screen.
useDeferredValue를 사용하면 서버 API 호출 수가 줄어드는가?
아니다. useDeferredValue는 화면 그리기(렌더링)를 미루는 것이지 네트워크 요청을 줄이는 것이 아니다. 키를 누를 때마다 서버 요청은 여전히 발생하며, 결과를 보여주는 시점만 조절된다.
useDeferredValue does not by itself prevent extra network requests.
Note that there is still a network request per each keystroke.
What’s being deferred here is displaying results (until they’re ready), not the network requests themselves.
useDeferredValue의 기본 타임아웃은 몇 밀리초인가?
고정된 지연 시간은 없다. useDeferredValue 자체가 타이머를 설정하는 것이 아니라, React 내부 스케줄러가 상황에 맞게 업데이트 시점을 결정한다.
There is no fixed delay caused by useDeferredValue itself.
느린 컴포넌트를 useDeferredValue로 감싸면 렌더링이 빨라지는가?
렌더링 자체가 빨라지는 것은 아니다. 대신 입력 필드 같은 급한 업데이트를 먼저 처리하고, 느린 목록의 렌더링은 뒤로 미룬다. 목록이 입력보다 살짝 늦게 따라오지만 키 입력이 버벅거리지 않게 되는 효과다.
useDeferredValue lets you prioritize updating the input (which must be fast) over updating the result list (which is allowed to be slower):
This does not make re-rendering of the SlowList faster.
However, it tells React that re-rendering the list can be deprioritized so that it doesn’t block the keystrokes.
The list will “lag behind” the input and then “catch up”.
Like before, React will attempt to update the list as soon as possible, but will not block the user from typing.
무거운 deferred 렌더링이 메인 스레드를 점유하면 다음 키 입력이 지연되지 않는가?
백그라운드 렌더링은 중단 가능하다. 사용자가 키를 누르면 React는 진행 중이던 무거운 렌더링을 즉시 포기하고 키 입력을 먼저 처리한 뒤, 새 값으로 백그라운드 렌더링을 다시 시작한다.
The background re-render is interruptible: if there’s another update to the value, React will restart the background re-render from scratch.
For example, if the user is typing into an input faster than a chart receiving its deferred value can re-render, the chart will only re-render after the user stops typing.
As soon as React finishes the original re-render, React will immediately start working on the background re-render with the new deferred value.
Any updates caused by events (like typing) will interrupt the background re-render and get prioritized over it.
useDeferredValue는 디바운싱이나 쓰로틀링과 어떻게 다른가?
디바운싱과 쓰로틀링은 고정된 시간을 정해놓고 업데이트를 지연하지만, useDeferredValue는 사용자 기기 성능에 맞춰 자동으로 조절된다. 또한 백그라운드 렌더링이 중단 가능하므로 키 입력을 막지 않는 반면, 디바운싱/쓰로틀링은 렌더링 자체를 막을 수 없어 버벅임이 생길 수 있다.
There are two common optimization techniques you might have used before in this scenario:
Debouncing means you’d wait for the user to stop typing (e.g. for a second) before updating the list.
Throttling means you’d update the list every once in a while (e.g. at most once a second).
While these techniques are helpful in some cases, useDeferredValue is better suited to optimizing rendering because it is deeply integrated with React itself and adapts to the user’s device.
Unlike debouncing or throttling, it doesn’t require choosing any fixed delay.
If the user’s device is fast (e.g. powerful laptop), the deferred re-render would happen almost immediately and wouldn’t be noticeable.
If the user’s device is slow, the list would “lag behind” the input proportionally to how slow the device is.
Also, unlike with debouncing or throttling, deferred re-renders done by useDeferredValue are interruptible by default.
This means that if React is in the middle of re-rendering a large list, but the user makes another keystroke, React will abandon that re-render, handle the keystroke, and then start rendering in the background again.
By contrast, debouncing and throttling still produce a janky experience because they’re blocking: they merely postpone the moment when rendering blocks the keystroke.
If the work you’re optimizing doesn’t happen during rendering, debouncing and throttling are still useful. For example, they can let you fire fewer network requests. You can also use these techniques together.