Suggest an editImprove this articleRefine the answer for “What does startTransition() do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`startTransition()`** tells React that the updates inside it are not urgent, and they can be deferred, paused, or canceled, so the interface stays instantly responsive to the user. **Key point:** do the important things (typing, clicks) now, and the heavy ones later, when there's time.Shown above the full answer for quick recall.Answer (EN)Image## In short: what `startTransition()` does > `startTransition()` tells React that **the updates inside it are not urgent**, > and they can be **deferred, paused, or canceled**, > so the interface stays **instantly responsive** to the user. Put simply: > "Do the important things (typing, clicks) now, and the heavy ones later, when there's time." --- ## 1. The problem without `startTransition()` Before React 18, every `setState()` call had the same priority. If the UI performed a heavy operation (for example, filtering a large list), the interface could **freeze up** until React finished rendering. ### Example without `startTransition()`: ```javascript function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); function handleChange(e) { const value = e.target.value; setQuery(value); // input setResults(filterBigList(value)); // heavy operation } return ( <> <input value={query} onChange={handleChange} /> <ResultsList items={results} /> </> ); } ``` The problem: while typing, React renders the list on every character, the input field **lags behind**. --- ## 2. The solution: `startTransition()` React 18 lets you mark a "heavy" update as *low priority*: ```javascript import { startTransition } from 'react'; function handleChange(e) { const value = e.target.value; setQuery(value); // urgent (high priority) startTransition(() => { setResults(filterBigList(value)); // deferred (low priority) }); } ``` Now: - React **updates the input instantly** (high priority); - the "list render" happens **later**, when the thread is free; - if the user keeps typing, React **cancels** the old filtering and starts a new one. --- ## 3. How it works internally When React sees `startTransition(callback)`: 1. React **puts the updates inside the callback into a separate queue** - the **"transitions"** queue (low priority); 2. All regular `setState()` calls outside `startTransition` **stay urgent**; 3. React runs the urgent tasks first (for example, text input); 4. Then, when the thread is free, React **resumes** the transition; 5. If a new urgent update arrives in the meantime, React **interrupts the transition** and starts a new one (so the interface stays always up to date). --- ## 4. Syntax and usage ### In a function component: ```javascript import { startTransition } from 'react'; startTransition(() => { setState(...); // any low-priority update }); ``` ### Or through the hook: ```javascript const [isPending, startTransition] = useTransition(); ``` (this version also lets you track the pending status, `isPending`) --- ## 5. Example with `isPending` (via useTransition) ```javascript function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isPending, startTransition] = useTransition(); function handleChange(e) { const value = e.target.value; setQuery(value); startTransition(() => { setResults(filterBigList(value)); }); } return ( <> <input value={query} onChange={handleChange} /> {isPending && <span>Updating list...</span>} <ResultsList items={results} /> </> ); } ``` Behavior: - `setQuery()` updates the field immediately; - `setResults()` renders asynchronously; - `isPending` shows an indicator until the transition finishes. --- ## 6. The difference between a regular update and a transition | Characteristic | Regular update (`setState`) | Transition (`startTransition`) | |---|---|---| | Priority | High (urgent) | Low (deferred) | | Can be interrupted | No | Yes | | When it runs | Immediately | When there's free time | | Used for | Input, clicks, animations | Filtering, loading, rebuilding the UI | | Effect on UX | Can lag | Smooth UI | --- ## 7. React decides the priorities itself React splits all updates into two types: - **Urgent** - come from user actions (typing, clicking); - **Transition** - less important, can run later. React runs urgent events **immediately**, and transitions **in the background**, **without blocking the interface**. --- ## 8. What's new in React 19 In **React 19**, `startTransition()` started **understanding async/await**: now you can wait for async operations inside a Transition to finish. ```javascript await startTransition(async () => { const data = await fetch('/api/products').then(res => res.json()); setProducts(data); }); ``` Before (in React 18), `startTransition()` only accepted a synchronous function - async code had to be wrapped manually. --- ## 9. When to use `startTransition()` Use `startTransition()` for: - filtering / sorting / searching a large list; - loading data after an interaction; - switching tabs or routes, if it requires rendering a large tree; - updates that are not critical to instant UX. Don't use it for: - click / focus / input events, they must be **urgent**; - small UI updates (icons, loaders, etc.). --- ## Summary > `startTransition()` is a way to mark state updates as *low priority*. > > React runs them **asynchronously and smoothly**, so the UI doesn't freeze. > > It's ideal for "heavy" or non-urgent interface changes. --- ### Quick cheat sheet | What it does | Key idea | |---|---| | `startTransition(callback)` | Marks updates as "non-urgent" | | Does it "freeze" the UI? | No, the UI stays responsive | | Can it be canceled / paused | Yes | | Works only in Concurrent Mode | Yes (`createRoot()`) | | Returns a `Promise` (in React 19+) | Yes | | Typical scenarios | Filtering, navigation, sorting, loading data |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.