React Holiday

#23: Spead up sluggish inputs with useDeferredValue

There’s an amazing hook that we haven’t yet covered: useDeferredValue. It has a scary name but its function is simple.

Consider a controlled React input that both displays and updates a piece of state:

<input
  type="text"
  value={term}
  onChange={(e) => {
    updateTerm(e.currentTarget.value);
  }}
/>

If this is the only component on the page, feedback is snappy!

But let’s introduce a little chaos.

[...Array(20000)].map(() => {
  return <p>{searchTerm}</p>;
});

This fills the page with 20k paragraphs using the search term on state. And, just like that, our input becomes slow — very slow.

Check out this GIF where I’m typing as fast as I can.

GIF of search input and many paragraphs showing the search term. As text is added to the input, it updates slowly but in sync with the paragraphs.

useDeferredValue gives us a way to separate high priority updates from low priority updates for cases like this.

Good news, we can keep the input exactly as it is. By default, React treats this as a high priority update.

But that army of p tags using the search term can be reduced to a low priority update. So we create a “deferred value” for them to use that lags behind searchTerm.

let deferredTerm = React.useDeferredValue(term)

Then update the p tags to use the deferred value.

<p>{deferredTerm}</p>

Everything that uses the deferred value will be await higher priority updates.

GIF of search input and many paragraphs showing the search term. As text is added to the input, the input updates immediately. But the p tags delay slightly before matching the input text.

Get into the code here.

🐦 chantastic