Suggest an editImprove this articleRefine the answer for “What does useTransition() do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)`useTransition()` lets you mark part of a state update as a **"transition"** - that is, a *lower-priority update* that React can **defer** in favor of more important ones (such as text input, clicks, animations). **Key point:** it is a way to tell React "this update is not urgent - do it a bit later".Shown above the full answer for quick recall.Answer (EN)Image## What `useTransition()` does > `useTransition()` lets you mark part of a state update as a **"transition"** - > that is, a *lower-priority update* that React can **defer** > in favor of more important ones (such as text input, clicks, animations). In simpler terms: > This is a way to tell React: > "This update is not urgent - you can do it a bit later, > once you're done with the fast stuff." --- ## Example without `useTransition` ```javascript function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); function handleChange(e) { const value = e.target.value; setQuery(value); // Emulate heavy filtering const filtered = hugeList.filter(item => item.includes(value)); setResults(filtered); } return ( <> <input value={query} onChange={handleChange} /> <ul>{results.map(r => <li key={r}>{r}</li>)}</ul> </> ); } ``` The problem: when typing fast, React re-renders the huge list on every character, which makes the **input "lag"** - the cursor stutters and updates slow down. --- ## 1. The solution with `useTransition` ```javascript import { useState, 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); // update the input right away (high priority) startTransition(() => { // update the results later (low priority) const filtered = hugeList.filter(item => item.includes(value)); setResults(filtered); }); } return ( <> <input value={query} onChange={handleChange} /> {isPending && <p>Loading...</p>} <ul>{results.map(r => <li key={r}>{r}</li>)}</ul> </> ); } ``` What React does: 1. `setQuery()` runs **immediately** → the input field stays responsive; 2. React defers `setResults()` - this is a "transition update"; 3. While the transition runs → `isPending = true` (you can show a loader); 4. When React finishes the transition, `isPending` resets. The UI stays smooth, typing is instant, the list updates a bit later, but without lag. --- ## What happens "under the hood" React now has **two update priorities**: | Update type | Example | Priority | |---|---|---| | Urgent | Text input, clicks, scrolling | Runs immediately | | Transition | Filtering, loading data, switching tabs | Can be paused | When you call `startTransition(fn)`: - React **puts the updates inside** `fn` **into a low-priority queue**; - it processes urgent updates first (for example, rendering the input); - then, when it's "free", it runs the transition; - if the user does something during the transition → React can **interrupt** the transition and start over (without freezing). --- ## 2. Asynchronous scenarios: API requests ```javascript import { useState, useTransition, Suspense } from 'react'; import useSWR from 'swr'; const fetcher = url => fetch(url).then(r => r.json()); function SearchResults({ query }) { const { data } = useSWR(`/api/search?q=${query}`, fetcher, { suspense: true }); return <ul>{data.results.map(r => <li key={r}>{r}</li>)}</ul>; } export function Search() { const [query, setQuery] = useState(''); const [displayQuery, setDisplayQuery] = useState(''); const [isPending, startTransition] = useTransition(); function handleChange(e) { const value = e.target.value; setQuery(value); startTransition(() => setDisplayQuery(value)); // asynchronous transition } return ( <> <input value={query} onChange={handleChange} /> {isPending && <p>Loading...</p>} <Suspense fallback={<p>Loading results...</p>}> <SearchResults query={displayQuery} /> </Suspense> </> ); } ``` What the code does: - the user types fast → React **updates the input instantly**; - `displayQuery` updates "deferred" → `SWR` triggers a fetch; - until the data arrives → React shows the `Suspense` fallback; - everything is smooth, without blocking the interface. --- ## 3. The values `useTransition()` returns ```javascript const [isPending, startTransition] = useTransition(); ``` | Variable | Description | |---|---| | `isPending` | true while the transition is running (you can show a loader / disable a button) | | `startTransition(cb)` | runs a function as a "deferred" state update | --- ## 4. The difference from `useDeferredValue()` | Hook | What it does | When to use it | |---|---|---| | `useTransition()` | defers *running a state update* | when you **set** state (`setState`) | | `useDeferredValue()` | defers *using a value* | when you **pass** a value into a heavy component | Example: ```javascript // useTransition startTransition(() => setQuery(value)); // update state deferred // useDeferredValue const deferredQuery = useDeferredValue(query); // use the value deferred ``` --- ## 5. Real-world cases | Scenario | How it helps | |---|---| | Searching a large list | instant typing, filtering deferred | | Switching between tabs | the old tab stays until the new one is ready | | Updating tables / charts | smooth UI while filtering | | Navigating to another page (SPA) | React shows the "old" page until the new one loads | | Suspense + API | background data loading without blocking | --- ## 6. What happens visually | Without `useTransition` | With `useTransition` | |---|---| | The UI freezes while typing | The UI is responsive | | New content replaces the old one instantly (flickers) | The old content stays until the new one is ready | | The transition feels "harsh" | The transition is smooth and natural | --- ## SUMMARY | What it does | Why it matters | |---|---| | Defers "heavy" updates | The UI stays responsive | | Separates priorities | React doesn't block input and clicks | | Returns `isPending` | you can show an indicator | | Works with Suspense | smooth async transitions | | Simplifies UX with large data | filters, search, sorting | --- ### In short: > `useTransition()` is a way to tell React: > "These updates aren't urgent - do them when you're free." > > It makes the UI **instantly responsive**, > even when there is **asynchronous data loading or a heavy render** happening under the hood.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.