DEV3 Technologies home

DEV3 Developer Forum

How do I stream data from a server component to a client component with the React 19 use() hook?

Next.js helpSolved0 views
dev3 ·

I want the page shell to render immediately and a slow client-side list to load in without blocking. I heard you can pass a promise as a prop and read it with use(). How does that look?

#nextjs#react#use-hook#streaming

0

1 reply

dev3 · Accepted answer

Start the fetch in a server component without awaiting it, pass the promise to a client component, and unwrap it with use() inside <Suspense>.

// app/orders/page.tsx (server)
import { Suspense } from "react";
import { getOrders } from "@/lib/orders";
import OrderList from "./order-list";

export default function Page() {
  const ordersPromise = getOrders(); // not awaited
  return (
    <>
      <h1>Orders</h1>
      <Suspense fallback={<p>Loading orders...</p>}>
        <OrderList ordersPromise={ordersPromise} />
      </Suspense>
    </>
  );
}
// app/orders/order-list.tsx
"use client";
import { use, useState } from "react";

type Order = { id: string; total: number };

export default function OrderList({ ordersPromise }: { ordersPromise: Promise<Order[]> }) {
  const orders = use(ordersPromise);
  const [min, setMin] = useState(0);
  return (
    <>
      <input type="number" onChange={(e) => setMin(+e.target.value)} />
      <ul>{orders.filter((o) => o.total >= min).map((o) => <li key={o.id}>{o.id}</li>)}</ul>
    </>
  );
}

Why use it

  • Shell HTML is flushed right away; the list streams in later.
  • The client component keeps interactivity (filtering, sorting) over data the server fetched.

Rules

  • The promise must be created on the server (or be stable). Creating a new promise during client render makes it suspend forever.
  • Resolved values must be serialisable.
  • If the promise rejects, the nearest error boundary (error.tsx) handles it. Catch inside getOrders if you want a fallback value.
  • If the data does not need client interactivity, simply make the list a server component and await inside it, wrapped in Suspense.
0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.