JAVASCRIPT

Improve Responsiveness with `useDeferredValue`

Leverage React 18's `useDeferredValue` hook to keep your UI responsive by deferring non-urgent updates, ensuring immediate feedback for user interactions like typing in a search bar.

import React, { useState, useDeferredValue } from 'react';

// A component that simulates an expensive rendering operation (e.g., a long list render)
function ExpensiveList({ query }) {
  const items = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`);

  const filteredItems = items.filter(item =>
    item.toLowerCase().includes(query.toLowerCase())
  );

  // Simulate a delay to emphasize the deferred effect
  let startTime = performance.now();
  while (performance.now() - startTime < 3) {
    // Block rendering for 3ms
  }

  return (
    <div>
      <h3>Results for "{query}" ({filteredItems.length} items)</h3>
      <ul style={{ maxHeight: '200px', overflowY: 'auto', border: '1px solid #ccc' }}>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

function SearchBarWithDeferred() {
  const [inputValue, setInputValue] = useState('');
  // Defer the value that will be passed to the ExpensiveList component.
  // This means the ExpensiveList will render with a "stale" value temporarily,
  // allowing the input to update immediately.
  const deferredQuery = useDeferredValue(inputValue);

  return (
    <div>
      <h1>Search with Deferred Value</h1>
      <p>Type into the search bar. Notice how the input remains responsive even during list updates.</p>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="Search for items..."
        style={{ width: '300px', padding: '8px', fontSize: '16px' }}
      />
      <hr />
      {/* Pass the deferredQuery to the expensive component */}
      <ExpensiveList query={deferredQuery} />
    </div>
  );
}

export default SearchBarWithDeferred;
How it works: `useDeferredValue` is a React 18 hook that lets you defer re-rendering a non-urgent part of your UI. When `inputValue` changes, `setInputValue` updates immediately, keeping the input responsive. However, `deferredQuery` will "lag" behind `inputValue`. React will prioritize the `inputValue` update (the urgent one) and then, in the background, will update the `deferredQuery` and re-render the `ExpensiveList` with the new value. This mechanism ensures that user interactions feel immediate, even when a subsequent UI update might be computationally intensive or take longer to render. It's particularly useful in scenarios like search bars with live filtering, where the input field should always respond instantly, while the filtered results can update slightly later without blocking the main thread.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs