Skip to content
Docs
Generative UI
createStreamableUI

createStreamableUI

createStreamableUI

Create a piece of changable UI that can be streamed to the client. On the client side, it can be rendered as a normal React node.

Parameters

Any valid React.ReactNode can be passed in such as string or array. But it will always be a UI node as a result and the client side can only render it, but not deconstructing it. Think of createStreamableUI('hello') gives you <>hello<>.

Returns

This creates a special value that can be returned from Actions to the client. It holds a UI node inside and can be updated via the update method.

Methods

update

The update method is used to update the UI node. It takes a new UI node and replaces the old one.

append

The append method is used to append a new UI node to the end of the old one. Once appended a new UI node, the previous UI node cannot be updated anymore.

done

The done method marks the UI node as finalized. You can either call it without any parameters or with a new UI node as the final state. Once called, the UI node cannot be updated or appended anymore.

The done method is always required to be called, otherwise the response will be stuck in a loading state.

Example

UI Streams are created on the server and streamed to the client.

app/action.tsx
import { createStreamableUI } from "ai/rsc";
 
async function confirmPurchase(symbol: string, amount: number) {
  "use server";
 
  const price = getStockPrice(symbol);
 
  const uiStream = createStreamableUI(
    <div className="inline-flex gap-1">
      {spinner}
      <p className="mb-2">
        Purchasing {amount} ${symbol}...
      </p>
    </div>
  );
 
  // This async function is immediately invoked but it will not block the
  // return statement. Because of that, the client will receive the initial
  // UI immediately and then the updates will be streamed later.
  (async () => {
    await sleep(1000);
 
    uiStream.update(
      <div className="inline-flex gap-1">
        {spinner}
        <p className="mb-2">
          Purchasing {amount} ${symbol}... working on it...
        </p>
      </div>
    );
 
    await sleep(1000);
 
    uiStream.done(
      <div>
        <p className="mb-2">
          You have successfully purchased {amount} ${symbol}.
          Total cost: ${amount * price}
        </p>
      </div>
    );
  })();
 
  return {
    id: Date.now(),
    display: uiStream.value,
  }
}

© 2023 Vercel Inc.