Skip to main content
Bojan Gvozderac
Download CV

Please note that my resume in its current form has been edited and stripped of a lot of experiences and projects to be easier to read and communicate better what experiences I find most valuable / relevant.

If you'd like to get to know me better and my career journey feel free to reach out on the contact page.

React.useDeferredValue

React.useDeferredValue
Did you know that React has a build in debounce hook?!

Well, sort of...

I’m talking about useDeferredValue hook, and it’s almost does what you think it does.
It doesn’t debounce in the generalized way like, for example, Lodash.debounce where a piece of logic is delayed until a certain time has passed since its last been called but rather it delays the rendering of the UI with the deferred value applied.
When you think about it for a second, in the context of React being a tool to render UI this makes a lot of sense!

Here’s an example of useDeferredValue in action:

function SearchPage() {
  const [query, setQuery] = React.useState('');
  const deferredQuery = React.useDeferredValue(query);
  // ...
}

It might not be obvious yet how useDeferredValue works so here’s the explainer from the docs:

“During the initial render, the returned deferred value will be the same as the value you provided.
During updates, React will first attempt a re-render with the old value (so it will return the old value), and then try another re-render in background with the new value (so it will return the updated value).”

Difference from throttle and debounce?

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 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.

For more info and examples (including using useDeferredValue with React Suspense) check out https://react.dev/reference/react/useDeferredValue

I'm an experienced web and mobile developer specializing in JavaScript with over a decade and a half developing software I have proven that I have the knowledge and the expertise to deliver the goods!
If you'd like to get in touch and talk about potential projects, one of my articles, ask a question or just say "Hi!" please do by emailing bojan.gvozderac@monarch-software.com.