Skip to content


The experimental_StreamingReactResponse class allows you to stream React component responses.


This API has been deprecated and will be removed in a future release. See Generative UI for the recommended approach to streaming React UI.

experimental_StreamingReactResponse(res: ReadableStream, options?: ResponseOptions): Response

The experimental_StreamingReactResponse class is designed to facilitate streaming React responses in a server action environment. It can handle and stream both raw content and data payloads, including special UI payloads, through nested promises.


res: ReadableStream

This parameter should be a ReadableStream, which encapsulates the HTTP response's content. It represents the stream from which the response is read and processed.

options?: {ui?: Function, data?: StreamData}

This optional parameter allows additional configurations for rendering React components and handling streamed data.

The options object can include:

  • ui?: (message: {content: string, data?: JSONValue[] | undefined}) => UINode | Promise<UINode>: A function that receives a message object with content and optional data fields. This function should return a React component (as UINode) for each chunk in the stream. The data attribute in the message is available when the data option is configured to include stream data.
  • data?: StreamData: An instance of StreamData used to process and stream data along with the response.


The method returns a Promise<ReactResponseRow>, which resolves to the next row of the React response. Each row contains a payload with UI components (ui), raw content (content), and a next property pointing to the subsequent row or null if it's the last row. This setup allows for continuous streaming and rendering of data in a React-based UI.


Server-Side Implementation

This example highlights the usage of experimental_StreamingReactResponse specifically within a server action context in a Next.js environment. It is crucial to note that this functionality is only available when used in server actions. For more details on server actions, visit Next.js Documentation on Server Actions (opens in a new tab).

In this server-side script, the handler function interacts with the OpenAI API to process and stream chat completions. The responses are streamed using OpenAIStream and subsequently managed by experimental_StreamingReactResponse for dynamic React component rendering.


'use server';
import OpenAI from 'openai';
import { OpenAIStream, experimental_StreamingReactResponse, Message } from 'ai';
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY!,
export async function handler({ messages }: { messages: Message[] }) {
  // Request the OpenAI API for the response based on the prompt
  const response = await{
    model: 'gpt-3.5-turbo',
    stream: true,
    messages: messages as any,
  // Convert the response into a friendly text-stream
  const stream = OpenAIStream(response);
  // Respond with the stream
  return new experimental_StreamingReactResponse(stream, {
    ui({ content }) {
      return (
        <div className="italic text-red-800">
          {content} Visit Next.js docs at{' '}

Client-Side Setup

On the client side, the useChat hook from ai/react is utilized to manage the chat interaction. The Chat component below renders the chat interface, including input forms and message displays. It dynamically integrates the server-side stream, displaying messages and UI elements as they are received.

import { handler } from './action';
import { Chat } from './chat';
export const runtime = 'edge';
export default function Page() {
  return <Chat handler={handler} />;
'use client';
import { useChat } from 'ai/react';
export function Chat({ handler }: { handler: any }) {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: handler,
  return (
    <div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
        {, index) => (
          <li key={index}>
            {m.role === 'user' ? 'User: ' : 'AI: '}
            {m.role === 'user' ? m.content : m.ui}
      <form onSubmit={handleSubmit}>
          className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl"
          placeholder="What is the weather in New York?"

© 2023 Vercel Inc.