Capítulo 108 de 116

Chapter 108: React DOM Server — Static & Resume APIs

Core Idea

Four smaller server APIs round out the react-dom/server surface: two non-streaming, string-returning renderers (renderToStaticMarkup, renderToString) for simpler/legacy cases, and two APIs (resume, resumeToPipeableStream) for continuing a previously-prerendered response.

Key Concepts

  • renderToStaticMarkup(reactNode): renders to a plain HTML string with no React-specific attributes added (no data attributes React would otherwise use for hydration) — appropriate for genuinely static output, like generating an email's HTML or a static site page that will never hydrate into an interactive React app on the client.
  • renderToString(reactNode): also returns an HTML string synchronously, but includes what's needed for later client hydration (Ch 95) — the legacy, non-streaming way to server-render a page meant to become interactive; the docs steer new code toward the streaming APIs (Ch 106/107) instead, since a synchronous string render can't take advantage of Suspense-driven streaming.
  • resume(reactNode, postponedState, options): continues rendering a tree from a previously postponed render (produced by the prerender APIs, Ch 109) — part of the "prerender now, resume later with final data" pattern for combining static generation with dynamic per-request completion.
  • resumeToPipeableStream(reactNode, postponedState, options): the Node streaming variant of resume, producing a pipeable stream instead of a complete result.
  • When to reach for the simple string renderers: only for content that's genuinely static (no hydration needed) or in constrained legacy contexts — for anything that needs to become an interactive client app, prefer the streaming render APIs with Suspense.

Key Takeaways

  1. renderToStaticMarkup is for non-interactive HTML output (emails, fully static pages); renderToString is the legacy interactive-hydration path, superseded by the streaming APIs.
  2. resume/resumeToPipeableStream exist specifically to complete a render that was deliberately paused ("postponed") by a prerender step — not a general resumption mechanism for arbitrary interrupted renders.
  3. New projects should default to renderToPipeableStream/renderToReadableStream (Ch 106-107) over the synchronous string renderers, to get Suspense-driven streaming.

Connects To

  • Ch 109 (Static Prerender APIs): where the "postponed state" that resume continues from actually comes from.
  • Ch 95 (hydrateRoot): the client-side counterpart for output from renderToString.