new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React · API reference · all subjects

react-dom/server

104 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

renderToString API

renderToString renders a React tree to a string. It is a legacy API available in environments that do not support streams and has limited functionality compared to streaming APIs.

renderToStaticMarkup API

renderToStaticMarkup renders a non-interactive React tree to a string. It is a legacy API available in environments that do not support streams and has limited functionality compared to streaming APIs.

react-dom/server overview and purpose

The react-dom/server APIs enable server-side rendering of React components to HTML. These APIs are used only on the server at the top level of an application to generate the initial HTML. A framework may call them automatically. Most components do not need to import or use them directly.

renderToReadableStream API

renderToReadableStream renders a React tree to a Readable Web Stream. It is available in environments that support Web Streams, which includes browsers, Deno, and some modern edge runtimes.

resume API

resume resumes prerender to a Readable Web Stream. It is available in environments that support Web Streams, which includes browsers, Deno, and some modern edge runtimes.

Web Streams APIs compatibility with Node.js

Node.js includes renderToReadableStream and resume for compatibility, but these methods are not recommended due to worse performance. The dedicated Node.js APIs should be used instead.

renderToPipeableStream API

renderToPipeableStream renders a React tree to a pipeable Node.js Stream. It is available in environments that support Node.js Streams and is the recommended method for Node.js environments over Web Stream APIs.

resumeToPipeableStream API

resumeToPipeableStream resumes prerenderToNodeStream to a pipeable Node.js Stream. It is available in environments that support Node.js Streams.

renderToReadableStream shell concept

The shell is the part of an app outside of any Suspense boundaries. It determines the earliest loading state that users see. The Promise returned by renderToReadableStream resolves as soon as the entire shell has been rendered. The shell should be designed to feel minimal but complete, like a skeleton of the page layout, rather than including the entire app or just a spinner.

renderToReadableStream onError callback behavior

The onError callback fires whenever there is a server error, whether recoverable or not. By default, errors only call console.error. If you override onError to log crash reports, you must still call console.error. You can use onError to adjust the status code before the shell is emitted. For errors outside the shell, onError fires but the Promise does not reject, allowing React to attempt recovery on the client.

renderToReadableStream error handling inside the shell

If an error occurs while rendering the shell, React will not have meaningful HTML to send. Wrap renderToReadableStream in a try-catch block to send fallback HTML if shell rendering fails. The Promise will be rejected if shell rendering fails, triggering the catch block.

renderToReadableStream status code handling

Once streaming starts, you can no longer change the response status code. By dividing your app into a shell (outside Suspense boundaries) and the rest, errors in the shell trigger a catch block where you can set error status code. Errors outside the shell do not reject the Promise, so use the onError callback to set a didError flag that determines the status code. For shell errors, use the catch block to set 500 status. For outside-shell errors detected in onError, you can send 500 status based on the flag.

renderToReadableStream abort signal for timeout

You can force server rendering to stop after a timeout by creating an AbortController and passing its signal to renderToReadableStream. Use setTimeout to call controller.abort() after the desired timeout. React will then flush remaining loading fallbacks as HTML and attempt to render the rest on the client.

renderToReadableStream for crawlers and static generation with allReady

For crawlers or static generation, await stream.allReady before returning the response. This makes React wait for all content to load before producing the final HTML output, rather than streaming progressively. Regular visitors get progressively loaded content while crawlers get the complete HTML after all data loads.

renderToReadableStream requires Web Streams API

renderToReadableStream depends on Web Streams API. For Node.js environments, use renderToPipeableStream instead.

renderToReadableStream example with streaming Suspense

Example showing streaming with Suspense boundaries: ```js function ProfilePage() { return ( <ProfileLayout> <ProfileCover /> <Suspense fallback={<PostsGlimmer />}> <Posts /> </Suspense> </ProfileLayout> ); } ``` React streams ProfileLayout and ProfileCover immediately, then streams PostsGlimmer while Posts loads, finally replacing it with Posts content.

renderToReadableStream example with nested Suspense

Example showing nested Suspense boundaries for granular streaming: ```js function ProfilePage() { return ( <ProfileLayout> <ProfileCover /> <Suspense fallback={<BigSpinner />}> <Sidebar> <Friends /> <Photos /> </Sidebar> <Suspense fallback={<PostsGlimmer />}> <Posts /> </Suspense> </Suspense> </ProfileLayout> ); } ``` This creates a more granular loading sequence with multiple fallbacks.

renderToReadableStream example with error handling

Example showing error handling with onError callback: ```js async function handler(request) { const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'], onError(error) { console.error(error); logServerCrashReport(error); } }); return new Response(stream, { headers: { 'content-type': 'text/html' }, }); } ```

renderToReadableStream example with shell error catch block

Example showing try-catch for shell errors: ```js async function handler(request) { try { const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'] }); return new Response(stream, { headers: { 'content-type': 'text/html' }, }); } catch (error) { return new Response('<h1>Something went wrong</h1>', { status: 500, headers: { 'content-type': 'text/html' }, }); } } ```

renderToReadableStream example with status code based on error flag

Example showing status code determination based on errors outside shell: ```js async function handler(request) { try { let didError = false; const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'], onError(error) { didError = true; console.error(error); } }); return new Response(stream, { status: didError ? 500 : 200, headers: { 'content-type': 'text/html' }, }); } catch (error) { return new Response('<h1>Something went wrong</h1>', { status: 500, headers: { 'content-type': 'text/html' }, }); } } ```

renderToReadableStream example with custom error types and status codes

Example showing handling different error types: ```js async function handler(request) { let didError = false; let caughtError = null; function getStatusCode() { if (didError) { if (caughtError instanceof NotFoundError) { return 404; } else { return 500; } } else { return 200; } } try { const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'], onError(error) { didError = true; caughtError = error; console.error(error); } }); return new Response(stream, { status: getStatusCode(), headers: { 'content-type': 'text/html' }, }); } catch (error) { return new Response('<h1>Something went wrong</h1>', { status: getStatusCode(), headers: { 'content-type': 'text/html' }, }); } } ```

renderToReadableStream example with allReady for crawlers

Example showing stream.allReady usage for crawlers: ```js async function handler(request) { try { const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'] }); let isCrawler = // ... bot detection strategy ... if (isCrawler) { await stream.allReady; } return new Response(stream, { status: 200, headers: { 'content-type': 'text/html' }, }); } catch (error) { return new Response('<h1>Something went wrong</h1>', { status: 500, headers: { 'content-type': 'text/html' }, }); } } ```

renderToReadableStream example with abort signal timeout

Example showing timeout-based abortion of server rendering: ```js async function handler(request) { try { const controller = new AbortController(); setTimeout(() => { controller.abort(); }, 10000); const stream = await renderToReadableStream(<App />, { signal: controller.signal, bootstrapScripts: ['/main.js'] }); return new Response(stream, { headers: { 'content-type': 'text/html' }, }); } catch (error) { return new Response('<h1>Something went wrong</h1>', { status: 500, headers: { 'content-type': 'text/html' }, }); } } ```

renderToReadableStream App component must render entire document

The root component rendered by renderToReadableStream should return the entire document including the root `<html>` tag, along with `<head>` containing metadata and `<body>` containing the application structure. React will inject the doctype and bootstrap scripts into the final output.

renderToReadableStream signature and basic usage

renderToReadableStream is imported from 'react-dom/server'. Its signature is `const stream = await renderToReadableStream(reactNode, options?)`. It renders a React tree as HTML into a Readable Web Stream. The reactNode parameter should be a React node representing the entire document, typically the root component that renders the `<html>` tag. It returns a Promise that resolves to a Readable Web Stream.

renderToReadableStream options parameter

renderToReadableStream accepts an optional options object with the following properties: bootstrapScriptContent (string, optional) - inline script content; bootstrapScripts (array of strings, optional) - URLs for `<script>` tags; bootstrapModules (array of strings, optional) - URLs for `<script type="module">` tags; identifierPrefix (string, optional) - prefix for IDs generated by useId, must match hydrateRoot's prefix; namespaceURI (string, optional) - root namespace URI, defaults to regular HTML, use 'http://www.w3.org/2000/svg' for SVG or 'http://www.w3.org/1998/Math/MathML' for MathML; nonce (string, optional) - nonce string for Content-Security-Policy script-src; onError (function, optional) - callback fired on server errors; progressiveChunkSize (number, optional) - number of bytes in a chunk; signal (AbortSignal, optional) - abort signal to cancel server rendering.

renderToReadableStream return value and stream.allReady

renderToReadableStream returns a Promise. If the shell renders successfully, it resolves to a Readable Web Stream. If shell rendering fails, the Promise is rejected. The returned stream has an additional property: allReady, which is a Promise that resolves when all rendering is complete, including both the shell and all additional content. You can await stream.allReady before returning a response for crawlers and static generation, which will prevent progressive loading.

renderToReadableStream basic example

Example showing basic renderToReadableStream usage: ```js import { renderToReadableStream } from 'react-dom/server'; async function handler(request) { const stream = await renderToReadableStream(<App />, { bootstrapScripts: ['/main.js'] }); return new Response(stream, { headers: { 'content-type': 'text/html' }, }); } ```

React injects doctype and bootstrap scripts into HTML stream

React automatically injects the HTML doctype and bootstrap `<script>` tags into the resulting HTML stream. Bootstrap scripts are emitted with the async attribute. For example, if bootstrapScripts is ['/main.js'], React will add `<script src="/main.js" async=""></script>` to the stream.

Client hydration with hydrateRoot after renderToReadableStream

After rendering server HTML with renderToReadableStream, call hydrateRoot on the client to make the server-generated HTML interactive. The client bootstrap script should call hydrateRoot with the entire document: `hydrateRoot(document, <App />);`. This attaches event listeners to the server-generated HTML.

renderToReadableStream Suspense boundary streaming behavior

Wrap components in `<Suspense>` boundaries to enable streaming. React sends the HTML for the shell (content outside Suspense boundaries) first, then progressively streams the HTML for each Suspense boundary as its data loads. The user sees content progressively rather than waiting for everything. Nested Suspense boundaries create a more granular loading sequence. Only data read from sources that activate Suspense boundaries (like Promises read with use) will suspend during rendering.

renderToPipeableStream signature

The renderToPipeableStream function is called with a React node and optional options object, and returns an object with pipe and abort methods. Signature: const { pipe, abort } = renderToPipeableStream(reactNode, options?)

renderToPipeableStream parameters

renderToPipeableStream accepts the following parameters: reactNode: A React node to render to HTML. Expected to represent the entire document, so the root component should render the <html> tag. options (optional): An object with streaming options: - bootstrapScriptContent (optional string): An inline <script> tag content. - bootstrapScripts (optional string array): URLs for <script> tags to emit. Include the script that calls hydrateRoot. - bootstrapModules (optional string array): Like bootstrapScripts, but emits <script type="module"> tags. - identifierPrefix (optional string): A string prefix React uses for IDs generated by useId. Must match the prefix passed to hydrateRoot. - namespaceURI (optional string): Root namespace URI for the stream. Defaults to regular HTML. Pass 'http://www.w3.org/2000/svg' for SVG or 'http://www.w3.org/1998/Math/MathML' for MathML. - nonce (optional string): A nonce string to allow scripts for script-src Content-Security-Policy. - onAllReady (optional callback): Fires when all rendering is complete, including shell and additional content. Use instead of onShellReady for crawlers and static generation. - onError (optional callback): Fires whenever there is a server error, whether recoverable or not. Receives the error as an argument. By default calls console.error. - onShellReady (optional callback): Fires right after the initial shell has been rendered. Can set status code and call pipe to start streaming here. - onShellError (optional callback): Fires if there was an error rendering the initial shell. Receives the error as an argument. No bytes were emitted yet. - progressiveChunkSize (optional number): The number of bytes in a chunk.

renderToPipeableStream basic usage example

import { renderToPipeableStream } from 'react-dom/server'; app.use('/', (request, response) => { const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } }); });

renderToPipeableStream root component structure

The root component passed to renderToPipeableStream should return the entire document including the root <html> tag. For example: export default function App() { return ( <html> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="/styles.css"></link> <title>My app</title> </head> <body> <Router /> </body> </html> ); }

renderToPipeableStream injects doctype and scripts

React automatically injects the doctype and bootstrap script tags into the resulting HTML stream. The output will include <!DOCTYPE html> at the start and <script> tags for the bootstrap scripts specified in the options.

renderToPipeableStream client-side hydration

On the client side, the bootstrap script should call hydrateRoot to make the server-generated HTML interactive. Example: import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot(document, <App />);

renderToPipeableStream with hashed asset URLs

When asset URLs are hashed after build, the root component can read filenames from an assetMap prop: export default function App({ assetMap }) { return ( <html> <head> <link rel="stylesheet" href={assetMap['styles.css']}></link> </head> </html> ); } On the server: const assetMap = {'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js'}; const { pipe } = renderToPipeableStream(<App assetMap={assetMap} />, { bootstrapScripts: [assetMap['main.js']], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } });

renderToPipeableStream passing assetMap to client

Pass the assetMap to the client by serializing it with bootstrapScriptContent: const assetMap = {'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js'}; const { pipe } = renderToPipeableStream(<App assetMap={assetMap} />, { bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`, bootstrapScripts: [assetMap['main.js']], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); } }); On the client, access it with: hydrateRoot(document, <App assetMap={window.assetMap} />);

renderToPipeableStream with Suspense for streaming

Use Suspense boundaries to enable streaming of content as it loads. Content outside Suspense boundaries (the shell) renders first, then Suspense-wrapped content streams after: function ProfilePage() { return ( <ProfileLayout> <ProfileCover /> <Suspense fallback={<PostsGlimmer />}> <Posts /> </Suspense> </ProfileLayout> ); }

renderToPipeableStream nested Suspense boundaries

Nest Suspense boundaries to create granular loading sequences: function ProfilePage() { return ( <ProfileLayout> <ProfileCover /> <Suspense fallback={<BigSpinner />}> <Sidebar> <Friends /> <Photos /> </Sidebar> <Suspense fallback={<PostsGlimmer />}> <Posts /> </Suspense> </Suspense> </ProfileLayout> ); } React can start streaming the page after rendering ProfileLayout and ProfileCover. The HTML for BigSpinner fallback is sent while Sidebar, Friends, or Photos load data.

renderToPipeableStream shell definition

The shell is the part of your app outside of any Suspense boundaries. It determines the earliest loading state that the user may see. The shell should feel minimal but complete, like a skeleton of the entire page layout. The onShellReady callback fires when the entire shell has been rendered.

renderToPipeableStream error handling with onError

Override the onError callback to handle server errors and log crash reports: const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); }, onError(error) { console.error(error); logServerCrashReport(error); } }); If you provide a custom onError implementation, remember to also log errors to the console.

renderToPipeableStream recovering from shell errors

If an error occurs while rendering the shell, use onShellError to send a fallback HTML: const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { response.setHeader('content-type', 'text/html'); pipe(response); }, onShellError(error) { response.statusCode = 500; response.setHeader('content-type', 'text/html'); response.send('<h1>Something went wrong</h1>'); }, onError(error) { console.error(error); logServerCrashReport(error); } }); When a shell error occurs, both onError and onShellError callbacks will fire. Use onError for error reporting and onShellError to send the fallback HTML.

renderToPipeableStream recovering from Suspense boundary errors

If an error happens in a component wrapped in Suspense (outside the shell), React will try to recover by: emitting the loading fallback for the closest Suspense boundary into the HTML; giving up on server rendering of that content; retrying rendering on the client when JavaScript loads. If client rendering also fails, the error is thrown on the client. The onError callback will fire so you can log the error.

renderToPipeableStream setting status code

Set the response status code in onShellReady. You can also track errors and set different status codes based on error type: let didError = false; const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { response.statusCode = didError ? 500 : 200; response.setHeader('content-type', 'text/html'); pipe(response); }, onShellError(error) { response.statusCode = 500; response.setHeader('content-type', 'text/html'); response.send('<h1>Something went wrong</h1>'); }, onError(error) { didError = true; console.error(error); } }); Once streaming starts, you can't change the status code.

renderToPipeableStream with custom error types

Use custom Error subclasses to handle different errors differently: let didError = false; let caughtError = null; function getStatusCode() { if (didError) { if (caughtError instanceof NotFoundError) { return 404; } else { return 500; } } else { return 200; } } const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { response.statusCode = getStatusCode(); response.setHeader('content-type', 'text/html'); pipe(response); }, onShellError(error) { response.statusCode = getStatusCode(); response.setHeader('content-type', 'text/html'); response.send('<h1>Something went wrong</h1>'); }, onError(error) { didError = true; caughtError = error; console.error(error); } });

renderToPipeableStream onAllReady for crawlers

Use onAllReady instead of onShellReady for crawlers and static generation to wait for all content to load: let didError = false; let isCrawler = // ... depends on your bot detection strategy ... const { pipe } = renderToPipeableStream(<App />, { bootstrapScripts: ['/main.js'], onShellReady() { if (!isCrawler) { response.statusCode = didError ? 500 : 200; response.setHeader('content-type', 'text/html'); pipe(response); } }, onAllReady() { if (isCrawler) { response.statusCode = didError ? 500 : 200; response.setHeader('content-type', 'text/html'); pipe(response); } }, onError(error) { didError = true; console.error(error); } }); This lets regular visitors see progressive content while crawlers wait for all data to load.

renderToPipeableStream abort method

Use the abort method to force server rendering to stop after a timeout: const { pipe, abort } = renderToPipeableStream(<App />, { // ... }); setTimeout(() => { abort(); }, 10000); React will flush the remaining loading fallbacks as HTML and attempt to render the rest on the client.

renderToPipeableStream Node.js specific

renderToPipeableStream is specific to Node.js. For environments with Web Streams like Deno and modern edge runtimes, use renderToReadableStream instead.

renderToPipeableStream Suspense activation

Only data read from a source that activates a Suspense boundary, such as a Promise read with use(), will suspend during rendering. Suspense does not detect data fetched inside an Effect or event handler.

renderToStaticMarkup parameters

renderToStaticMarkup accepts two parameters: (1) reactNode (required) - a React node you want to render to HTML, such as a JSX node like <Page />; (2) options (optional) - an object for server render containing identifierPrefix, a string prefix React uses for IDs generated by useId, useful to avoid conflicts when using multiple roots on the same page.

renderToStaticMarkup signature

renderToStaticMarkup renders a non-interactive React tree to an HTML string. The signature is: const html = renderToStaticMarkup(reactNode, options?)

renderToStaticMarkup return value

renderToStaticMarkup returns an HTML string.

renderToStaticMarkup cannot be hydrated

renderToStaticMarkup output cannot be hydrated. The output is non-interactive HTML.

renderToStaticMarkup Suspense support

renderToStaticMarkup has limited Suspense support. If a component suspends, renderToStaticMarkup immediately sends its fallback as HTML.

renderToStaticMarkup browser usage not recommended

renderToStaticMarkup works in the browser, but using it in client code is not recommended. If you need to render a component to HTML in the browser, get the HTML by rendering it into a DOM node instead.

renderToStaticMarkup use case

renderToStaticMarkup is useful if you want to use React as a simple static page generator, or if you are rendering completely static content like emails. Interactive apps should use renderToString on the server and hydrateRoot on the client instead.

renderToStaticMarkup example usage

Example of rendering a React component to HTML in a server route handler: ```js import { renderToStaticMarkup } from 'react-dom/server'; app.use('/', (request, response) => { const html = renderToStaticMarkup(<Page />); response.send(html); }); ``` This produces the initial non-interactive HTML output of your React components.

renderToString parameters

renderToString accepts two parameters: (1) reactNode - a React node to render to HTML, such as a JSX element like <App />; (2) options (optional) - an object with an optional identifierPrefix property, which is a string prefix React uses for IDs generated by useId. The identifierPrefix must be the same prefix as passed to hydrateRoot to avoid conflicts when using multiple roots on the same page.

Give your agent this brain