React 19 use API

Unwrap promises and consume context conditionally in render with the revolutionary React 19 use API.

TL;DR

  1. Unwrap asynchronous promises directly in render with use.
  2. Read context conditionally inside if statements and loops.
  3. Coordinate promise resolution seamlessly with parent Suspense boundaries.

Unwrapping Promises with use

    Direct Promise Reading

    Read resolved promise data synchronously in render.

    function Comments({ commentsPromise }: Props) {
      const list = use(commentsPromise);
      return <ListView items={list} />;
    }
    Suspense Boundary Integration

    Suspends component until promise completes.

    <Suspense fallback={<CardSkeleton />}>
      <Comments commentsPromise={fetchComments()} />
    </Suspense>
    Streaming Server Promise

    Receive preloaded promise from Server Component.

    // In Server Component: pass promise without await
    <ClientFeed stream={getDataPromise()} />

Conditional Context Reading

    Context in if Statement

    Read context only when specific condition met.

    function Header({ showTheme }: Props) {
      if (!showTheme) return <Text>Plain</Text>;
      const theme = use(ThemeContext);
      return <CardView color={theme.bg} />;
    }
    Context in Loop

    Call use inside array iteration safely.

    const configs = contexts.map((ctx) => use(ctx));
    Dynamic Context Selection

    Choose which context to read based on props.

    const val = use(isAdmin ? AdminCtx : UserCtx);

use API Rules and Gotchas

    External Promise Creation

    Instantiate promise outside render lifecycle.

    // GOOD: Promise created in loader or server
    const userPromise = fetchUser(userId);
    Render Loop Antipattern

    Instantiating promise inside render loops infinitely.

    // BAD: Creates new promise every render
    const data = use(fetch('/api'));
    Error Boundary Handling

    Catch rejected promises with standard ErrorBoundary.

    <ErrorBoundary fallback={<Text>Load failed</Text>}>
      <Suspense fallback={<Skeleton />}>
        <DataView promise={p} />
      </Suspense>
    </ErrorBoundary>

Streaming Data Architectures

    Parallel Promise Unwrapping

    Unwrap multiple data streams independently.

    const user = use(userPromise);
    const stats = use(statsPromise);
    Selective Fallbacks

    Isolate individual promise suspensions cleanly.

    <Suspense fallback={<UserSkeleton />}>
      <UserCard promise={uPromise} />
    </Suspense>
    Client Action Cache Passing

    Pass refreshed promise from action into use.

    const nextPromise = refetch();
    setPromise(nextPromise);

Tips

  1. Call use(promise) to unwrap values directly during component render, letting parent Suspense boundaries handle pending fallback states.
  2. Leverage use(ThemeContext) inside conditional branches or loops where standard Hook rules previously disallowed useContext calls.

Warnings

  1. Never create promises inside component render bodies passed to use; promises must be created outside or in server components.
  2. Always ensure components invoking use(promise) are wrapped inside a valid <Suspense> boundary to prevent uncaught suspensions.

In Practice

FAQ