Що робить Suspense у React 18?
Що таке Suspense
<Suspense>- це компонент-обгортка, який дозволяє призупиняти рендеринг частини інтерфейсу, поки не будуть готові якісь дані (або компоненти), і показувати запасний UI (fallback) замість "завислої" ділянки.
Простіше кажучи:
Suspense= «Покажи скелет/спінер, поки React чекає дані або модуль».
Основна ідея
До React 18 Suspense працював тільки для лінивого завантаження компонентів (через React.lazy).
У React 18 він став універсальним інструментом очікування:
тепер він вміє працювати з асинхронними даними, серверним рендерингом і стрімінгом.
Приклад базового використання
import React, { Suspense, lazy } from 'react';
const Profile = lazy(() => import('./Profile'));
function App() {
return (
<Suspense fallback={<div>Loading profile...</div>}>
<Profile />
</Suspense>
);
}Поки компонент Profile завантажується,
React призупиняє його рендер і показує <div>Loading profile...</div>.
Коли модуль підвантажиться - React "відновить" рендер і вставить готовий компонент.
Що нового з'явилося в React 18
1. Suspense тепер працює на сервері (SSR)
React 18 додав стрімінговий серверний рендеринг:
- тепер сервер може віддавати HTML частинами,
- і Suspense дозволяє рендерити "готові шматки" одразу, не чекаючи, поки весь застосунок буде повністю зібраний.
Приклад:
<Suspense fallback={<Skeleton />}>
<Comments />
</Suspense>Якщо <Comments> завантажується довше - React на сервері:
- віддає HTML без цього блоку;
- показує
Skeleton; - пізніше "дострімить" готовий HTML блоку
<Comments>; - на клієнті відбудеться гідратація без ривків.
Нові API для цього:
renderToPipeableStream() // для Node.js
renderToReadableStream() // для Deno, Edge та ін.2. Suspense тепер розуміє асинхронні дані (через бібліотеки)
React 18 сам по собі ще не вміє "fetch-ити" дані, але Suspense тепер може чекати Promise, якщо його кидає компонент або хук. Це використовується у фреймворках (Next.js 13+, Remix, RSC).
Наприклад, у Next.js:
export default async function Page() {
const user = await getUser(); // async-компонент
return (
<Suspense fallback={<Spinner />}>
<UserInfo user={user} />
</Suspense>
);
}React автоматично призупинить рендер, поки getUser() не завершиться,
а в цей час покаже Spinner.
3. Сумісність з Concurrent Rendering
Suspense заснований на конкурентному рендерингу React 18.
Це означає, що React може:
- призупиняти рендер компонента,
- продовжувати рендер інших частин UI,
- відновлювати рендер пізніше - без блокування інтерфейсу.
Тобто React буквально "рендерить наперед", але не показує компонент, поки він не готовий.
4. Новий рівень UX
Suspense вирішує проблему "смикання інтерфейсу":
- немає різкого зникнення контенту під час завантаження;
- можна показувати placeholder / skeleton плавно;
- можна комбінувати
Suspenseдля різних частин сторінки (nested Suspense).
Приклад:
<Suspense fallback={<MainSkeleton />}>
<MainContent />
<Suspense fallback={<SidebarSkeleton />}>
<Sidebar />
</Suspense>
</Suspense>5. Як React "зупиняє" рендер
Механіка проста:
- Всередині компонента виникає Promise (наприклад, при лінивому імпорті або завантаженні даних);
- React "зустрічає" цей Promise;
- Він зупиняє рендер цієї частини дерева;
- Показує
fallback; - Коли Promise виконано -> React відновлює рендер з реальними даними.
6. Що Suspense не робить сам по собі
- Не виконує запити (
fetch,axios) напряму - він лише керує очікуванням. - Не керує помилками (
catch) - для цього потрібен<ErrorBoundary>. - Не замінює
useEffect- Suspense використовується під час рендера, а не після.
Підсумок
<Suspense>- це декларативний механізм очікування: React призупиняє рендер частини дерева, показує fallback, а потім автоматично відновлює рендер, коли дані або модулі готові.
Коротко:
| Можливість | React 17 | React 18 |
|---|---|---|
| Lazy loading компонентів | Так | Так |
| Очікування даних (Promise) | Ні | Так |
| SSR + Streaming | Ні | Так |
| Кілька рівнів Suspense | Обмежено | Стабільно |
| Підтримка Concurrent Rendering | Ні | Так |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.