Конкурентний рендеринг у React
Що таке Конкурентний Рендеринг?
Конкурентний рендеринг (React 18+) дозволяє React перервати роботу рендерингу, щоб обробити більш термінові оновлення. Замість того, щоб синхронно рендерити все дерево (блокуючи), React може працювати над кількома версіями інтерфейсу одночасно, призупиняючи та відновлюючи за потреби.
Синхронний vs Конкурентний
До React 18 (Синхронний)
Користувач вводить → React рендерить 10,000 елементів → UI заморожено → Оновлення введення
^^^^^^^^^^^^^^^^^^^^^^^^
Не може бути перервано!React 18+ (Конкурентний)
Користувач вводить → React починає рендеринг → Користувач вводить знову → React ПРИПИНЯЄ
React перезапускається з останнім введенням → Рендерить → UI оновлюється
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Можна перервати! Пріоритетно!Ключові Концепції
1. Переривний Рендеринг
React може призупинити роботу над оновленням низького пріоритету, щоб обробити оновлення високого пріоритету (наприклад, введення користувача), а потім відновити пізніше.
2. Автоматичне Пакування
React 18 автоматично пакує всі оновлення стану, навіть у асинхронних функціях:
// React 17 — кожен setState викликає окремий повторний рендер у асинхронному
setTimeout(() => {
setCount(c => c + 1); // Повторний рендер 1
setFlag(f => !f); // Повторний рендер 2
}, 1000);
// React 18 — автоматично упаковано в ОДИН повторний рендер
setTimeout(() => {
setCount(c => c + 1); // Упаковано
setFlag(f => !f); // Упаковано → Один повторний рендер
}, 1000);3. Транзакції
Позначайте не термінові оновлення за допомогою startTransition:
import { startTransition } from "react";
// Терміново: показати те, що ввів користувач
setInputValue(input);
// Нетерміново: фільтрувати та відображати результати
startTransition(() => {
setSearchResults(filterItems(input));
});4. Підвіс для Отримання Даних
function App() {
return (
<Suspense fallback={<PageSkeleton />}>
<Header />
<Suspense fallback={<ContentSkeleton />}>
<MainContent /> {/* Потоки, коли готові */}
</Suspense>
<Suspense fallback={<CommentsSkeleton />}>
<Comments /> {/* Потоки незалежно */}
</Suspense>
</Suspense>
);
}Підсумок Конкурентних Функцій
| Функція | Що вона робить | Хук / API |
|---|---|---|
| Автоматичне Пакування | Пакує всі оновлення стану | Вбудоване (React 18) |
| Транзакції | Позначає оновлення як нетермінові | useTransition, startTransition |
| Відкладені Значення | Відкладає оновлення значення | useDeferredValue |
| Потокове SSR | Відправляє HTML частинами | Suspense + сервер |
| Вибіркова Гідратація | Гідратує частини незалежно | Suspense + гідратація |
Як Увімкнути Конкурентний Рендеринг
// React 18 — використовуйте createRoot (увімкнення конкурентних функцій)
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root")!);
root.render(<App />);
// ❌ Спадщина — ReactDOM.render (без конкурентних функцій)
// ReactDOM.render(<App />, document.getElementById("root"));Практичні Переваги
// Без конкурентного рендерингу:
// Введення в полі пошуку затримується, оскільки React блокує фільтрацію 50,000 елементів
// З конкурентним рендерингом:
function Search({ items }: { items: Item[] }) {
const [query, setQuery] = useState("");
const [isPending, startTransition] = useTransition();
return (
<div>
<input
value={query}
onChange={e => {
setQuery(e.target.value); // Терміново: оновити введення
startTransition(() => { // Нетерміново: фільтрувати
setFilteredItems(filterItems(items, e.target.value));
});
}}
/>
{isPending && <Spinner />}
<ItemList items={filteredItems} />
</div>
);
}
// Введення залишається чутливим! Фільтрація відбувається у фоновому режимі.Важливо:
Конкурентний рендеринг є опційним для кожної функції — ваш існуючий код продовжує працювати. Увімкніть його за допомогою createRoot, а потім використовуйте useTransition та useDeferredValue, щоб позначити нетермінові оновлення. React автоматично обробляє пакування, переривання та пріоритизацію. Результат: програми, які відчуваються більш чутливими, особливо при важкому рендерингу або повільних даних.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.