use(resource) читає значення з проміса або контексту. На відміну від хуків, його можна викликати в умовах і циклах.
1. Читання проміса з Suspense:
import { use, Suspense } from 'react';
function Comments({ commentsPromise }) {
const comments = use(commentsPromise); // «призупиняє» компонент до виконання проміса
return comments.map((c) => <p key={c.id}>{c.text}</p>);
}
function Post({ commentsPromise }) {
return (
<Suspense fallback={<p>Завантаження коментарів...</p>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
);
}
Поки проміс виконується, показується fallback найближчого <Suspense>. Відхилений проміс потрапляє в найближчу межу помилок (error boundary).
Головна пастка - звідки береться проміс. Проміс, створений під час рендеру клієнтського компонента (use(fetch('/api/comments'))), буде новим на кожному рендері - React показуватиме fallback знову й знову. Проміс має бути стабільним:
- створений у серверному компоненті й переданий клієнтському як prop (основний сценарій у Next.js);
- закешований бібліотекою (TanStack Query, роутер з завантажувачами даних);
- створений поза рендером (в обробнику події, в завантажувачі маршруту).
2. Читання контексту:
function Toolbar({ showTheme }) {
if (showTheme) {
const theme = use(ThemeContext); // useContext тут заборонений правилами хуків
return <ThemeBadge theme={theme} />;
}
return null;
}
Що відрізняє use від хуків:
- можна викликати умовно і в циклах;
- але лише в компонентах і хуках - не в звичайних функціях і не в
try/catch(помилки обробляє error boundary, а неcatch); - не створює власного стану.
У серверних компонентах use для промісів не потрібен - там можна просто await. use - для клієнтських компонентів, що отримують проміс.
Чим це краще за useEffect для даних: немає проміжного стану «ще не завантажено» в кожному компоненті, немає гонитви запитів у ефектах, а стани завантаження й помилки декларативно задаються межами Suspense і error boundary.