Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

React 19+ · Function

renderToReadableStream

Renders a complete React tree as HTML into a Web ReadableStream, intended for streaming server rendering in Web Streams environments. The returned promise resolves when the shell is ready.

Since
18

How it works

The function asynchronously renders a React tree as HTML for Web Streams environments. Once the shell is ready, its promise resolves with a ReadableStream that can be placed in a Response; the stream also exposes allReady for waiting until every Suspense-dependent part has finished.

Syntax

const stream = await renderToReadableStream(reactNode, options?)

Parameters

NameTypeDescription
reactNodeReactNodeThe React node to render as HTML; it should represent the entire document, including the html element.
optionsobjectOptional object containing streaming options such as bootstrapScripts, signal, namespaceURI, and progressiveChunkSize.

Returns

A Promise resolving to a Readable Web Stream when the shell renders successfully; the promise rejects if shell rendering fails. The stream has an allReady Promise for completion of all content.

Key points

  • Use it for streaming server-rendered React HTML through the Web Streams API.
  • The output is HTML streamed from the server rather than a single eagerly assembled string.
  • The initial shell controls when the function becomes usable for constructing the response.
  • After waiting for allReady, the stream represents the completed document without progressive delivery.
  • Client hydration is the step that turns the streamed server markup into an interactive React application.

Common mistakes

  • This API relies on Web Streams, so Node.js applications should use the Node-oriented streaming API instead.
  • Awaiting allReady before sending the response produces complete HTML but disables progressive streaming.

Example: Stream a server-rendered document

import { renderToReadableStream } from 'react-dom/server';

function App() {
  return <html><body><h1>Hello</h1></body></html>;
}

export default async function handler() {
  const stream = await renderToReadableStream(<App />, {
    bootstrapScripts: ['/main.js'],
  });
  return new Response(stream, {
    headers: { 'content-type': 'text/html' },
  });
}

Renders the complete document into a Web ReadableStream and returns it as an HTTP response.

When to use it

Stream SSR HTML from a request handler

Edge or Web Streams server rendering

Reveal async content progressively

Suspense-based server rendering

Wait for allReady to send complete HTML

Crawlers and static generation

Pair bootstrap scripts with hydrateRoot

Client hydration

Interview questions

QWhat does renderToReadableStream return?

It returns a Promise because the shell may need asynchronous rendering before a stream can be provided. A successful shell resolves to a Readable Web Stream; a shell failure rejects the promise.

Follow-up: How would you serve crawlers? Await the returned stream’s allReady promise before returning the response, which sends final HTML instead of progressively revealed content.

QHow is it used in an edge-style request handler?

Pass the complete React document as reactNode and optionally provide an options object containing streaming configuration. The root component should produce the html element and the result can be used as the body of a Response.

Follow-up: How do you make the generated document interactive? Supply bootstrap scripts and hydrate the server HTML on the client with hydrateRoot.

QWhen should you choose this API over renderToPipeableStream?

The API is intended for runtimes implementing Web Streams, such as modern edge environments. For Node.js, the documentation directs you to renderToPipeableStream instead.

Follow-up: What trade-off does allReady introduce? It allows complete output suitable for crawlers or static generation, but removes progressive loading.

  • renderToPipeableStream
  • hydrateRoot
  • Suspense
  • allReady

Source: renderToReadableStream. Checked 2026-10-15.