Skip to main content
Juliano Alves
Back to blog

The use() hook, Suspense, and async data in React 19

3 min read
By Juliano Alves

React 19’s use API reads resources—currently context and promises—during render. When a promise is not yet resolved, React suspends the nearest <Suspense> boundary instead of forcing you into useEffect + useState boilerplate.

Reading a promise#

'use client';
import { use, Suspense } from 'react';

function UserName({ userPromise }: { userPromise: Promise<{ name: string }> }) {
  const user = use(userPromise);
  return <span>{user.name}</span>;
}

export function Profile({ userPromise }: { userPromise: Promise<{ name: string }> }) {
  return (
    <Suspense fallback={<span>Loading…</span>}>
      <UserName userPromise={userPromise} />
    </Suspense>
  );
}

The promise should be stable per request (create in Server Component and pass down, or from a cache layer)—do not create a fresh promise on every parent render without memoization or you will loop.

Comparison to useEffect#

useEffect runs after paint; use suspends before commit of that subtree. That improves perceived loading when paired with meaningful fallbacks.

Next.js interaction#

Server Components can await or pass promises to client boundaries. Verify your Next/React versions support the pattern you ship; frameworks evolve quickly.

Summary#

use + Suspense is a declarative async story on the client. Treat promises as first-class props, respect Suspense boundaries, and avoid recreating promises unintentionally.

© 2026 Juliano Alves. All rights reserved.