Write a useDeferredSearch hook that keeps old results, marked stale, while new ones render
Write useDeferredSearch(items, query, search). It returns { results, isStale }, where results is search(items, someQuery). The point is to keep a search box responsive next to a slow results list: the box should update at once, and the results should catch up in a background render that a newer key can interrupt.
So when query changes, the first (urgent) render must not search: it returns the results it already has, the very same array, with isStale: true. Then a background render searches with the new query and returns isStale: false. On the first render it searches with query straight away and isn't stale. A render for any other reason doesn't search again; a new items list or a new search function does. Here's how a component uses it:
const ResultList = memo(function ResultList({ results }) {
return <ul>{results.map((tea) => <li key={tea.id}>{tea.name}</li>)}</ul>;
});
function TeaSearch({ teas }) {
const [query, setQuery] = useState("");
const { results, isStale } = useDeferredSearch(teas, query, searchByName);
return (
<>
<input aria-label="Search" value={query} onChange={(e) => setQuery(e.target.value)} />
<section aria-busy={isStale} style={{ opacity: isStale ? 0.5 : 1 }}>
<ResultList results={results} />
</section>
</>
);
}
import { useDeferredValue, useMemo } from "react";
export function useDeferredSearch(items, query, search) {
// Search with a deferred copy of query, and say when the results are behind.
return { results: search(items, query), isStale: false };
}
- searches with the query on the first render, not stale
- a new query first returns the old results, marked stale, then the new ones
- the stale render returns the very same results array
- searches once per new query, in the background render only
- renders for other reasons don't search again
- a new items list or search function searches again
- a memo list renders once per key, and the section ends up not busy
The answer
Write it yourself first. Then compare it with a reference solution and the checks it passes.
Checking your sign-in…