useTransition lets you mark state updates as non-urgent, allowing React to prioritize interactions while preparing less urgent UI updates.
Imagine filtering thousands of items while a user types into a search input.
setFilter(value);
If updating the filter triggers expensive rendering, the input may become sluggish because React has to process a large amount of UI work.
useTransitionconst [isPending, startTransition] = useTransition();
startTransition: Marks state updates inside its callback as non-urgent.isPending: Indicates that the transition is still pending.function SearchPage({ items }) {const [input, setInput] = useState("");const [filter, setFilter] = useState("");const [isPending, startTransition] = useTransition();function handleChange(event) {const value = event.target.value;setInput(value); // Urgent updatestartTransition(() => {setFilter(value); // Non-urgent update});}const filteredItems = items.filter(item =>item.name.toLowerCase().includes(filter.toLowerCase()));return (<><input value={input} onChange={handleChange} />{isPending && <span>Updating results...</span>}<ul>{filteredItems.map(item => (<li key={item.id}>{item.name}</li>))}</ul></>);}
The input updates urgently, while the filter state update is marked as a transition. React can prioritize typing over rendering the updated results.
For very large datasets, consider memoizing the expensive list or using virtualization as well.
useTransition Does Not DoInstead, it allows React to schedule rendering work according to priority.
Use useTransition for expensive filtering, switching tabs, navigating between views, or rendering data-heavy UI where an update can wait while urgent interactions remain responsive.