Skip to content

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.

Author
Jan Jarčík
Published
Reading time
2 min read
Updated
ShareXLinkedInBluesky

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.

TSX
// 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>
  );
}
TSX
// 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

TSX
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.