Advanced Search with useTransition and useDeferredValue
Combined useTransition and useDeferredValue for responsive search with visual stale indicators
import { useState, useTransition, useDeferredValue, useMemo } from 'react';
function AdvancedSearch({ data }: { data: Item[] }) {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
const deferredQuery = useDeferredValue(query, '');
// Expensive filtering uses deferred value
const filteredResults = useMemo(
() => {
if (!deferredQuery) return [];
// Expensive operation - won't block input
return data.filter(item =>
item.name.toLowerCase().includes(deferredQuery.toLowerCase())
);
},
[data, deferredQuery]
);
const isStale = query !== deferredQuery;
const handleSearch = (value: string) => {
// Urgent: Update input immediately
setQuery(value);
// Non-urgent: Mark as transition
startTransition(() => {
// Filtering happens in background
});
};
return (
<div>
<input
value={query}
onChange={(e) => handleSearch(e.target.value)}
placeholder="Search..."
className={isPending ? 'opacity-50' : ''}
/>
{isPending && <Spinner />}
<div style={{ opacity: isStale ? 0.5 : 1 }}>
<ResultsList results={filteredResults} />
</div>
</div>
);
}