Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить useTransition()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`useTransition()` дозволяє позначити частину оновлень стану як **"перехід" (transition)** - тобто *менш пріоритетне оновлення*, яке React може **відкласти** заради важливіших (наприклад, вводу тексту, кліків, анімацій). **Ключове:** це спосіб сказати React "це оновлення не термінове - можеш зробити його трохи пізніше".Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `useTransition()` > `useTransition()` дозволяє позначити частину оновлень стану як **"перехід" (transition)** - > тобто *менш пріоритетне оновлення*, яке React може **відкласти** > заради важливіших (наприклад, вводу тексту, кліків, анімацій). Простіше кажучи: > Це спосіб сказати React: > "Це оновлення не термінове - можеш зробити його трохи пізніше, > коли закінчиш зі швидкими справами." --- ## Приклад без `useTransition` ```javascript function Search() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); function handleChange(e) { const value = e.target.value; setQuery(value); // Емулюємо важку фільтрацію 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> </> ); } ``` Проблема: при швидкому введенні React перемальовує величезний список на кожному символі, через що **input "лагає"** - курсор підвисає, а оновлення гальмують. --- ## 1. Рішення з `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); // оновлюємо input одразу (високий пріоритет) startTransition(() => { // оновлюємо результати пізніше (низький пріоритет) const filtered = hugeList.filter(item => item.includes(value)); setResults(filtered); }); } return ( <> <input value={query} onChange={handleChange} /> {isPending && <p>Завантаження...</p>} <ul>{results.map(r => <li key={r}>{r}</li>)}</ul> </> ); } ``` Що робить React: 1. `setQuery()` виконується **одразу** → поле вводу залишається відповідним; 2. React відкладає `setResults()` - це "transition update"; 3. Поки перехід виконується → `isPending = true` (можна показати loader); 4. Коли React завершить перехід - `isPending` скидається. UI залишається плавним, ввід миттєвий, список оновлюється трохи пізніше, але без лагів. --- ## Що відбувається "під капотом" React тепер має **два пріоритети оновлень**: | Тип оновлення | Приклад | Пріоритет | |---|---|---| | Термінове (Urgent) | Ввід тексту, кліки, скрол | Виконується одразу | | Відкладене (Transition) | Фільтрація, підвантаження даних, перемикання вкладок | Можна призупинити | Коли ти викликаєш `startTransition(fn)`: - React **ставить оновлення всередині** `fn` **у чергу з низьким пріоритетом**; - спочатку обробляє термінові оновлення (наприклад, рендер input); - потім, коли "вільний", запускає перехід; - якщо під час переходу користувач щось робить → React може **перервати** перехід і почати заново (без фризів). --- ## 2. Асинхронні сценарії: запити до API ```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)); // асинхронний перехід } return ( <> <input value={query} onChange={handleChange} /> {isPending && <p>Завантаження...</p>} <Suspense fallback={<p>Завантаження результатів...</p>}> <SearchResults query={displayQuery} /> </Suspense> </> ); } ``` Що робить код: - користувач швидко друкує → React **миттєво оновлює input**; - `displayQuery` оновлюється "відкладено" → `SWR` запускає fetch; - поки дані не прийшли → React показує fallback з `Suspense`; - усе плавно, без блокування інтерфейсу. --- ## 3. Значення, що повертає `useTransition()` ```javascript const [isPending, startTransition] = useTransition(); ``` | Змінна | Опис | |---|---| | `isPending` | true, поки виконується перехід (можна показати loader / вимкнути кнопку) | | `startTransition(cb)` | запускає функцію як "відкладене" оновлення стану | --- ## 4. Відмінність від `useDeferredValue()` | Хук | Що робить | Коли використовувати | |---|---|---| | `useTransition()` | відкладає *виконання оновлення стану* | коли ти **встановлюєш** стан (`setState`) | | `useDeferredValue()` | відкладає *використання значення* | коли ти **передаєш** значення у важкий компонент | Приклад: ```javascript // useTransition startTransition(() => setQuery(value)); // відкладено оновлюємо стан // useDeferredValue const deferredQuery = useDeferredValue(query); // відкладено використовуємо значення ``` --- ## 5. Реальні кейси | Сценарій | Як допомагає | |---|---| | Пошук по великому списку | миттєвий ввід, фільтрація відкладена | | Переходи між вкладками | стара вкладка залишається, поки нова не готова | | Оновлення таблиць / графіків | плавний UI при фільтрації | | Перехід на іншу сторінку (SPA) | React показує "стару" сторінку до завантаження нової | | Suspense + API | фонове підвантаження даних без блокування | --- ## 6. Що відбувається візуально | Без `useTransition` | З `useTransition` | |---|---| | UI зависає при вводі | UI відповідний | | Новий контент замінює старий миттєво (блимає) | Старий контент залишається, поки новий не готовий | | Перехід здається "жорстким" | Перехід плавний і природний | --- ## ПІДСУМОК | Що робить | Чому важливо | |---|---| | Відкладає "важкі" оновлення | UI залишається відповідним | | Розділяє пріоритети | React не блокує ввід і кліки | | Повертає `isPending` | можна показати індикатор | | Працює з Suspense | плавні async-переходи | | Спрощує UX при великих даних | фільтри, пошук, сортування | --- ### Коротко: > `useTransition()` - це спосіб сказати React: > "Ці оновлення не термінові - зроби їх, коли звільнишся." > > Він робить UI **миттєво відповідним**, > навіть якщо під капотом іде **асинхронне підвантаження даних або важкий рендер.**Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.