Skip to main content
Практика завдань

useTransition та useDeferredValue в React

Конкурентні можливості в React 18+

React 18 представив конкурентне рендеринг з двома основними хуками: useTransition та useDeferredValue. Вони дозволяють вам позначати певні оновлення стану як не термінові, зберігаючи інтерфейс користувача чутливим.


useTransition

useTransition дозволяє вам позначити оновлення стану як перехід — не термінове оновлення, яке може бути перервано більш терміновими оновленнями (наприклад, введенням користувача).

tsx
import { useState, useTransition } from "react"; function SearchPage() { const [query, setQuery] = useState(""); const [results, setResults] = useState<string[]>([]); const [isPending, startTransition] = useTransition(); const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const value = e.target.value; // ✅ Термінове: оновити введення негайно setQuery(value); // ✅ Не термінове: оновити результати в переході startTransition(() => { const filtered = heavyFilter(value); // витратна операція setResults(filtered); }); }; return ( <div> <input value={query} onChange={handleChange} /> {isPending && <Spinner />} <ResultList results={results} /> </div> ); }

Як працює useTransition

  1. isPending — булевий прапор, true під час виконання переходу
  2. startTransition(callback) — обгортає не термінове оновлення стану
  3. React може перервати перехід, якщо надходить більш термінове оновлення
  4. Введення залишається чутливим, оскільки важке оновлення відкладене

useDeferredValue

useDeferredValue створює відкладену копію значення, яка "відстає" від оригіналу. React оновлює його лише тоді, коли має вільну потужність.

tsx
import { useState, useDeferredValue, useMemo } from "react"; function SearchResults({ query }: { query: string }) { // Створює відкладену версію запиту const deferredQuery = useDeferredValue(query); const isStale = query !== deferredQuery; // Перераховує лише тоді, коли deferredQuery змінюється const results = useMemo( () => heavySearch(deferredQuery), [deferredQuery] ); return ( <div style={{ opacity: isStale ? 0.5 : 1 }}> {results.map(r => <div key={r.id}>{r.title}</div>)} </div> ); } function App() { const [query, setQuery] = useState(""); return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} /> <SearchResults query={query} /> </div> ); }

useTransition vs useDeferredValue

ОсобливістьuseTransitionuseDeferredValue
Що відкладеноОновлення стану (setState)Значення
Де використовуватиКоли ви володієте сеттером стануКоли у вас лише значення (пропси)
Повертає[isPending, startTransition]Відкладене значення
Індикатор очікуванняВбудований isPendingПорівняти оригінал з відкладеним

Коли використовувати який

tsx
// useTransition — ви контролюєте setState const [isPending, startTransition] = useTransition(); startTransition(() => { setFilteredList(expensiveFilter(items)); }); // useDeferredValue — ви отримуєте значення від батька function ChildComponent({ searchTerm }: { searchTerm: string }) { const deferredTerm = useDeferredValue(searchTerm); // Використовуйте deferredTerm для витратного рендерингу }

Реальні випадки використання

Перемикання вкладок

tsx
function TabContainer() { const [tab, setTab] = useState("home"); const [isPending, startTransition] = useTransition(); function selectTab(nextTab: string) { startTransition(() => { setTab(nextTab); // Важкий контент вкладки може рендеритися у фоновому режимі }); } return ( <div> <TabButtons onSelect={selectTab} activeTab={tab} /> {isPending ? <Spinner /> : <TabContent tab={tab} />} </div> ); }

Фільтрація великого списку

tsx
function FilterableList({ items }: { items: Item[] }) { const [filter, setFilter] = useState(""); const deferredFilter = useDeferredValue(filter); const filtered = useMemo( () => items.filter(item => item.name.includes(deferredFilter)), [items, deferredFilter] ); return ( <> <input value={filter} onChange={e => setFilter(e.target.value)} /> <ul style={{ opacity: filter !== deferredFilter ? 0.7 : 1 }}> {filtered.map(item => <li key={item.id}>{item.name}</li>)} </ul> </> ); }

Важливо:

useTransition та useDeferredValue — це функції React 18+ для збереження чутливості інтерфейсу під час витратних оновлень. Використовуйте useTransition, коли ви контролюєте сеттер стану, і useDeferredValue, коли ви отримуєте значення як пропс. Обидва стосуються пріоритизації термінових оновлень (введення користувача) над не терміновими (результати пошуку, важкі рендери).

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань