What does useTransition() do?
What useTransition() does
useTransition() lets you mark a state update as "transitional" (non-urgent)
so that React does not block the interface during heavy re-renders.
In simpler terms:
useTransition()tells React: "This update can happen later, do not stall the UI."
Syntax
const [isPending, startTransition] = useTransition();startTransition(callback)- wraps code that triggers an unhurried update.isPending- a boolean value (trueduring the transition), shows that React is still "rendering" the deferred state.
Example
Imagine you have a large amount of data, and the user types text to filter a list.
Without useTransition
function Search() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
// a heavy operation
setResults(filterBigData(value));
};
return (
<>
<input value={query} onChange={handleChange} />
<List data={results} />
</>
);
}The problem:
- Every keystroke (
setQuery) immediately triggers the heavyfilterBigData. - The UI "freezes" (lags) on every keypress.
With useTransition
import { useState, useTransition } from "react";
function Search() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
startTransition(() => {
// this update is not urgent
setResults(filterBigData(value));
});
};
return (
<>
<input value={query} onChange={handleChange} />
{isPending && <p>Loading...</p>}
<List data={results} />
</>
);
}Now:
- React first instantly updates
query(an urgent update), - and then, when there is time, does
setResults(unhurried), - while the interface stays responsive (you can keep typing).
What React does internally
React 18 has a Concurrent Renderer, which can pause and interrupt a render if something more important comes up, for example, the user is typing.
useTransition simply marks a piece of work as:
"It is fine if this waits."
React then:
- pauses the heavy render,
- shows the old UI,
- continues once the main thread frees up.
Returned values
| Variable | Type | Description |
|---|---|---|
isPending | boolean | true while the transition is not finished |
startTransition(callback) | function | wraps "unhurried" updates |
When to use useTransition()
| When | Why |
|---|---|
| Filtering, search, sorting in large lists | So typing does not freeze |
| Pagination or navigation between large components | So the transition does not freeze the UI |
| Dynamic data loading | So user actions are not blocked |
| When you need to visually separate "instant" and "deferred" updates | For example, isPending = true → show "Loading…" |
When not to use it
| Situation | Why |
|---|---|
Simple updates (setState in a button) | useTransition would complicate the code with no benefit |
| API requests or asynchronous data | Use useEffect or useQuery |
| You have no problem with UI "lag" | React already optimizes simple cases well enough |
Comparison with regular setState
| Update | What React does |
|---|---|
setState() | Runs immediately (high priority) |
startTransition(() => setState()) | Marked as "low priority", React may defer it |
Example: switching pages
function Tabs({ tabs }) {
const [active, setActive] = useState(0);
const [isPending, startTransition] = useTransition();
return (
<>
{tabs.map((tab, i) => (
<button
key={i}
onClick={() => startTransition(() => setActive(i))}
disabled={isPending}
>
{tab.title}
</button>
))}
<div>
{isPending ? <p>Loading tab...</p> : tabs[active].content}
</div>
</>
);
}Switching is instant, even if the tab content is large - React "loads" it calmly, without blocking the interface.
Summary
| Question | Answer |
|---|---|
What does useTransition() do | Lets you run low-priority (deferred) state updates |
| When React runs them | After urgent ones (typing, clicks, hover, etc.) |
| What it returns | [isPending, startTransition] |
| When to use it | For heavy computations, filtering, transitions between large components |
| When not to | For simple updates or asynchronous API requests |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.