Suggest an editImprove this articleRefine the answer for “What are "Transition Updates"?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **Transition Update** is a *low-priority* state update that React can **run later**, **pause**, or **cancel** if more important (urgent) user actions are happening right now. **Key point:** transitions are updates that can be deferred so they don't interfere with a fast UI response.Shown above the full answer for quick recall.Answer (EN)Image## What Transition Updates are > A **Transition Update** is a *low-priority* state update > that React can **run later**, **pause**, or **cancel**, > if more important (urgent) user actions are happening right now. In simpler terms: > **Transitions = updates that can be deferred**, > so they don't get in the way of a fast UI response. --- ## 1. The problem Transitions solve Before React 18, all calls to `setState()` were **equal**: React ran all updates with the same priority. ### Example: The user types text, and every keystroke filters a huge list: ```javascript function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); function handleChange(e) { const value = e.target.value; setQuery(value); setResults(filterBigList(value)); // heavy update } return ( <> <input value={query} onChange={handleChange} /> <ResultsList items={results} /> </> ); } ``` In React 17 the UI can "lag": the input freezes while React renders the list. --- ## 2. How React 18 solves this with Transition Updates Now you can mark **part of the updates** as *not urgent* (transitions): ```javascript import { useTransition } from 'react'; function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isPending, startTransition] = useTransition(); function handleChange(e) { const value = e.target.value; setQuery(value); // urgent update (typing) startTransition(() => { setResults(filterBigList(value)); // deferred (heavy) update }); } return ( <> <input value={query} onChange={handleChange} /> {isPending && <Spinner />} {/* while waiting */} <ResultsList items={results} /> </> ); } ``` Now: - the input field **updates instantly**; - React **defers** filtering the list; - you can show a loading indicator `isPending` while the Transition is not yet finished. --- ## 3. What `startTransition()` does under the hood 1. React receives the function passed into `startTransition()`; 2. it marks the updates inside as **low priority**; 3. if **urgent** updates arrive in the meantime (for example, keystrokes) - React **pauses the Transition** so the interface doesn't "freeze"; 4. as soon as the pipeline is free, React **resumes** the Transition. --- ## 4. "Urgent" vs "Transition" updates | Update type | Example | Priority | Can it be interrupted? | Example API | |---|---|---|---|---| | **Urgent** | Typing, clicks, focus, navigation | High | No | `setState()` directly | | **Transition (deferred)** | Filtering, sorting, loading data | Low | Yes | `startTransition()` / `useTransition()` | React now **understands the difference between what's UX-critical** and what's **resource-heavy**. --- ## 5. How React decides what to render first - React works with **two update queues**: - urgent (input, focus, scroll, etc.); - deferred (transitions). - If the user is typing, urgent updates go through **immediately**. - React can: - **defer** any transition until the next frame; - **pause** it if the user keeps typing; - **cancel** it if new data arrives; - **run it again**, once the user has stopped. --- ## 6. An example with the `isPending` indicator `useTransition()` returns: - `isPending` - a flag indicating that a Transition is currently running; - `startTransition(callback)` - a function to start low-priority updates. ```javascript const [isPending, startTransition] = useTransition(); startTransition(() => { setSearchResults(fetchFilteredResults(query)); }); ``` When React pauses the render, `isPending = true` - you can show a spinner, a skeleton, or "Loading…" text. --- ## 7. React manages Transitions itself Transitions only work **when Concurrent Rendering is active**, that is, when the application's root is created via: ```javascript import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')); root.render(<App />); ``` If you use the old `ReactDOM.render()`, `startTransition` simply has no effect - React cannot pause the render. --- ## 8. An example with asynchronous actions ```javascript function Products() { const [filter, setFilter] = useState('all'); const [data, setData] = useState([]); const [isPending, startTransition] = useTransition(); const handleFilter = (newFilter) => { startTransition(async () => { const res = await fetch(`/api/products?filter=${newFilter}`); const data = await res.json(); setData(data); setFilter(newFilter); }); }; return ( <> <Filters onChange={handleFilter} /> {isPending && <Skeleton />} <ProductList items={data} /> </> ); } ``` The UI stays responsive, even if the API request takes time. --- ## 9. What's new in React 19 React 19 improved Transitions - now `startTransition()` can be **asynchronous**: ```javascript await startTransition(async () => { await someAsyncOperation(); }); ``` There is no longer a need to manually manage the pending state - React itself knows when the Transition is done. --- ## Summary > **Transition Updates** are state updates > that React runs *smoothly*, *asynchronously*, and *without UI lag*, > deferring them while the user is interacting with the UI. --- ### A quick comparison | Characteristic | Regular `setState` | Transition Update | |---|---|---| | Priority | High | Low | | Can be interrupted | No | Yes | | UI delay | Possible (lag) | None | | Main use | UI events (typing, clicks) | Long computations, filters, loading | | API | `setState()` | `useTransition()` / `startTransition()` |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.