use(): the hook you're allowed to call conditionally
The new use() API reads a value from a Promise or a context. It integrates with Suspense and — uniquely — can be called inside an if.
use isn't a classic hook. It's an API that reads a value from a resource — a Promise or a context — and unlike other hooks you can call it inside conditions and loops.
Reading a Promise
When a component calls use(promise) and the promise is still pending, the component suspends and the closest <Suspense> fallback is shown. Once the promise resolves, React renders the component again with the value. If it rejects, the nearest Error Boundary takes over.
// app/page.tsx — Server Component
import { Suspense } from "react";
import { Comments } from "./Comments";
export default function Page() {
const commentsPromise = getComments(); // no await!
return (
<Suspense fallback={<p>Loading comments…</p>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
);
}// Comments.tsx
"use client";
import { use } from "react";
export function Comments({ commentsPromise }: { commentsPromise: Promise<Comment[]> }) {
const comments = use(commentsPromise);
return comments.map((c) => <p key={c.id}>{c.text}</p>);
}The Server Component starts fetching right away but doesn't wait — the page streams and the comments arrive later.
Beware of unstable promises
Don't create the promise inside a Client Component's render. Every render would create a new promise, the component would suspend again and you'd end up in a loop. The promise must be stable: coming from a Server Component, from a caching library (TanStack Query, SWR) or from a useMemo over stable inputs.
Context inside a condition
function Badge({ show }: { show: boolean }) {
if (!show) return null;
const theme = use(ThemeContext); // not possible with useContext
return <span className={theme.badge}>New</span>;
}use(Context) does the same thing as useContext, just more flexibly. In new components feel free to use use only.