Що таке "Transition Updates"?
Що таке Transition Updates
Transition Update - це низькопріоритетне оновлення стану, яке React може виконати пізніше, призупинити чи скасувати, якщо саме зараз відбуваються важливіші (термінові) дії користувача.
Простіше кажучи:
Transitions = оновлення, які можна відкласти, щоб не заважати швидкому відгуку UI.
1. Проблема, яку вирішують Transitions
До React 18 усі виклики setState() були рівнозначні:
React виконував усі оновлення з однаковим пріоритетом.
Приклад:
Користувач друкує текст, і при кожному введенні фільтрується величезний список:
function Search() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
function handleChange(e) {
const value = e.target.value;
setQuery(value);
setResults(filterBigList(value)); // важке оновлення
}
return (
<>
<input value={query} onChange={handleChange} />
<ResultsList items={results} />
</>
);
}У React 17 UI може "лагати": поле вводу підвисає, поки React рендерить список.
2. Як вирішує це React 18 з Transition Updates
Тепер можна позначити частину оновлень як нетермінові (transitions):
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); // термінове оновлення (ввід)
startTransition(() => {
setResults(filterBigList(value)); // відкладене (важке) оновлення
});
}
return (
<>
<input value={query} onChange={handleChange} />
{isPending && <Spinner />} {/* поки чекаємо */}
<ResultsList items={results} />
</>
);
}Тепер:
- поле вводу оновлюється миттєво;
- React відкладає фільтрацію списку;
- можна показати індикатор завантаження
isPending, поки Transition не завершений.
3. Що робить startTransition() під капотом
- React отримує функцію, передану в
startTransition(); - позначає оновлення всередині як низькопріоритетні;
- якщо в цей час приходять термінові оновлення (наприклад, натискання клавіш) - React призупиняє Transition, щоб інтерфейс не "завис";
- щойно потік звільняється - React відновлює виконання Transition.
4. "Термінові" vs "Перехідні" оновлення
| Тип оновлення | Приклад | Пріоритет | Можна перервати? | Приклад API |
|---|---|---|---|---|
| Urgent (термінові) | Набір тексту, кліки, фокус, навігація | Високий | Ні | setState() напряму |
| Transition (відкладені) | Фільтрація, сортування, підвантаження даних | Низький | Так | startTransition() / useTransition() |
React тепер розуміє різницю між UX-важливим і ресурсно-важким оновленням.
5. Як React вирішує, що рендерити першим
- React працює з двома чергами оновлень:
- терміновими (input, focus, scroll тощо);
- відкладеними (transitions).
- Якщо користувач вводить текст - термінові оновлення проходять негайно.
- Усі transitions React може:
- відкласти до наступного кадру;
- призупинити, якщо користувач продовжує ввід;
- скасувати, якщо прийшли нові дані;
- виконати заново, коли користувач зупинився.
6. Приклад з індикатором isPending
useTransition() повертає:
isPending- прапорець, що вказує, що Transition зараз виконується;startTransition(callback)- функцію для запуску низькопріоритетних оновлень.
const [isPending, startTransition] = useTransition();
startTransition(() => {
setSearchResults(fetchFilteredResults(query));
});Коли React призупиняє рендер, isPending = true -
можна показати спінер, скелетон чи напис "Завантаження…".
7. React сам керує Transitions
Transitions працюють лише при активному Concurrent Rendering, тобто коли корінь застосунку створений через:
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);Якщо ти використовуєш старий ReactDOM.render(), startTransition просто не дасть ефекту - React не зможе призупиняти рендер.
8. Приклад з асинхронними діями
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} />
</>
);
}UI залишається відповідним, навіть якщо запит до API займає час.
9. Нове в React 19
React 19 покращив Transitions - тепер startTransition() може бути асинхронним:
await startTransition(async () => {
await someAsyncOperation();
});Більше не потрібно вручну керувати станом очікування - React сам розуміє, коли Transition завершений.
Підсумок
Transition Updates - це оновлення стану, які React виконує плавно, асинхронно і без лагів інтерфейсу, відкладаючи їх, поки користувач взаємодіє з UI.
Коротке порівняння
| Характеристика | Звичайний setState | Transition Update |
|---|---|---|
| Пріоритет | Високий | Низький |
| Можна перервати | Ні | Так |
| Затримка в UI | Можлива (лаг) | Немає |
| Основне застосування | Події UI (ввід, клік) | Довгі обчислення, фільтри, завантаження |
| API | setState() | useTransition() / startTransition() |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.