React
April 12, 20252 min read...
ReactApril 12, 20252 min read

useTransition and useDeferredValue: Taming Expensive Renders

Learn React's concurrent rendering features – useTransition for marking non-urgent updates, useDeferredValue for deferring expensive re-renders. Practical examples and performance measurements.

useTransition and useDeferredValue: Taming Expensive Renders

Why Concurrent Features?

React 18 introduced concurrent rendering. Instead of blocking the main thread for expensive updates, you can mark some updates as 'transition' – letting urgent updates (like typing) jump ahead.

useTransition Example

import { useTransition, useState } from 'react';

function SearchPage() { const [isPending, startTransition] = useTransition(); const [query, setQuery] = useState(‘’); const [results, setResults] = useState([]);

function handleChange(e) { const value = e.target.value; setQuery(value); // urgent startTransition(() => { // non-urgent: expensive filtering const filtered = filterLargeList(value); setResults(filtered); }); }

return ( <div> <input value={query} onChange={handleChange} /> {isPending && <Spinner />} <Results data={results} /> </div> ); }

useDeferredValue Example

const [query, setQuery] = useState(‘’);
const deferredQuery = useDeferredValue(query);
// deferredQuery updates lag behind query
// perfect for expensive child components

return <ExpensiveList searchTerm={deferredQuery} />;

Performance Impact

Without transitions, typing into an input that filters 10,000 items would feel janky. With useTransition, typing stays smooth – the expensive filter runs in the background.

Common Mistakes

  • Wrapping every state update in startTransition – overuse adds overhead
  • Not showing pending indicator – users may think app is broken
  • Using with synchronous external stores – requires useSyncExternalStore

Interview Q&A

Q: Difference between useTransition and useDeferredValue? useTransition gives you a pending flag and control over which update is urgent. useDeferredValue just gives you a delayed value without flag.

Conclusion

Use useTransition for user-triggered updates (search, tabs, navigation). Use useDeferredValue for props that come from parent.

Comments

Join the conversation — sign in to leave a comment.