diff --git a/beta/src/content/apis/react-dom/client/createRoot.md b/beta/src/content/apis/react-dom/client/createRoot.md index de06195a..800350b9 100644 --- a/beta/src/content/apis/react-dom/client/createRoot.md +++ b/beta/src/content/apis/react-dom/client/createRoot.md @@ -233,7 +233,7 @@ It is uncommon to call `render` multiple times. Usually, you'll [update state](/ --- ## Reference {/*reference*/} -### `createRoot(domNode, options?)` {/*create-root*/} +### `createRoot(domNode, options?)` {/*createroot*/} Call `createRoot` to create a React root for displaying content inside a browser DOM element. @@ -256,10 +256,10 @@ An app fully built with React will usually only have one `createRoot` call for i * `domNode`: A [DOM element.](https://developer.mozilla.org/en-US/docs/Web/API/Element) React will create a root for this DOM element and allow you to call functions on the root, such as `render` to display rendered React content. -* **optional** `options`: A object contain options for this React root. +* **optional** `options`: An object with options for this React root. - * `onRecoverableError`: optional callback called when React automatically recovers from errors. - * `identifierPrefix`: optional prefix React uses for IDs generated by [`useId`.](/apis/react/useId) Useful to avoid conflicts when using multiple roots on the same page. + * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/apis/react/useId) Useful to avoid conflicts when using multiple roots on the same page. #### Returns {/*returns*/} diff --git a/beta/src/content/apis/react-dom/client/hydrateRoot.md b/beta/src/content/apis/react-dom/client/hydrateRoot.md index bdcbec51..f1403ad7 100644 --- a/beta/src/content/apis/react-dom/client/hydrateRoot.md +++ b/beta/src/content/apis/react-dom/client/hydrateRoot.md @@ -23,7 +23,7 @@ const root = hydrateRoot(domNode, reactNode, options?) If your app's HTML was generated by [`react-dom/server`](/apis/react-dom/client/createRoot), you need to *hydrate* it on the client. ```js [[1, 3, "document.getElementById('root')"], [2, 3, ""]] -import {hydrateRoot} from 'react-dom/client'; +import { hydrateRoot } from 'react-dom/client'; hydrateRoot(document.getElementById('root'), ); ```` @@ -44,7 +44,7 @@ To hydrate your app, React will "attach" your components' logic to the initial g ```js index.js active import './styles.css'; -import {hydrateRoot} from 'react-dom/client'; +import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( @@ -120,7 +120,7 @@ function App() { To hydrate the entire document, pass the [`document`](https://developer.mozilla.org/en-US/docs/Web/API/Window/document) global as the first argument to `hydrateRoot`: ```js {5} -import {hydrateRoot} from 'react-dom/client'; +import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( @@ -148,7 +148,7 @@ If you call `root.render` at some point after hydration, and the component tree ``` ```js index.js active -import {hydrateRoot} from 'react-dom/client'; +import { hydrateRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; @@ -183,7 +183,7 @@ It is uncommon to call [`root.render`](#root-render) on a hydrated root. Usually --- ## Reference {/*reference*/} -### `hydrateRoot(domNode, options?)` {/*hydrate-root*/} +### `hydrateRoot(domNode, options?)` {/*hydrateroot*/} Call `hydrateRoot` to “attach” React to existing HTML that was already rendered by React in a server environment. @@ -202,10 +202,11 @@ React will attach to the HTML that exists inside the `domNode`, and take over ma * `reactNode`: The "React node" used to render the existing HTML. This will usually be a piece of JSX like `` which was rendered with a `ReactDOM Server` method such as `renderToPipeableStream()`. -* **optional** `options`: A object contain options for this React root. +* **optional** `options`: An object with options for this React root. - * `onRecoverableError`: optional callback called when React automatically recovers from errors. - * `identifierPrefix`: optional prefix React uses for IDs generated by [`useId`.](/apis/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server. + * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. + * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/apis/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server. + * **optional** `nonce`: #### Returns {/*returns*/} diff --git a/beta/src/content/apis/react-dom/server/renderToNodeStream.md b/beta/src/content/apis/react-dom/server/renderToNodeStream.md index e6f5e04c..e089d60a 100644 --- a/beta/src/content/apis/react-dom/server/renderToNodeStream.md +++ b/beta/src/content/apis/react-dom/server/renderToNodeStream.md @@ -10,7 +10,7 @@ This API will be removed in a future major version of React. Use [`renderToPipea -`renderToNodeStream` renders a React tree to a [Node.js Readable stream.](https://nodejs.org/api/stream.html#readable-streams) +`renderToNodeStream` renders a React tree to a [Node.js Readable Stream.](https://nodejs.org/api/stream.html#readable-streams) ```js const stream = renderToNodeStream(reactNode) @@ -24,7 +24,7 @@ const stream = renderToNodeStream(reactNode) ## Usage {/*usage*/} -### Rendering a React tree as HTML to a Node.js Readable stream {/*rendering-a-react-tree-as-html-to-a-nodejs-readable-stream*/} +### Rendering a React tree as HTML to a Node.js Readable Stream {/*rendering-a-react-tree-as-html-to-a-nodejs-readable-stream*/} @@ -32,9 +32,11 @@ This API will be removed in a future major version of React. Use [`renderToPipea -Call `renderToNodeStream` to get a [Node.js Readable stream](https://nodejs.org/api/stream.html#readable-streams) which you can pipe to your server response: +Call `renderToNodeStream` to get a [Node.js Readable Stream](https://nodejs.org/api/stream.html#readable-streams) which you can pipe to your server response: + +```js {5-6} +import { renderToNodeStream } from 'react-dom/server'; -```js {3-4} // The route handler syntax depends on your backend framework app.use('/', (request, response) => { const stream = renderToNodeStream(); @@ -56,7 +58,7 @@ This API will be removed in a future major version of React. Use [`renderToPipea -On the server, call `renderToNodeStream` to get a [Node.js Readable stream](https://nodejs.org/api/stream.html#readable-streams) which you can pipe into the response. +On the server, call `renderToNodeStream` to get a [Node.js Readable Stream](https://nodejs.org/api/stream.html#readable-streams) which you can pipe into the response. ```js const stream = renderToNodeStream(); @@ -71,7 +73,7 @@ On the client, call [`hydrateRoot`](/apis/react-dom/client/hydrateRoot) to make #### Returns {/*returns*/} -A [Node.js Readable stream](https://nodejs.org/api/stream.html#readable-streams) that outputs an HTML string. +A [Node.js Readable Stream](https://nodejs.org/api/stream.html#readable-streams) that outputs an HTML string. #### Caveats {/*caveats*/} diff --git a/beta/src/content/apis/react-dom/server/renderToPipeableStream.md b/beta/src/content/apis/react-dom/server/renderToPipeableStream.md index 0382c01d..372f2fb6 100644 --- a/beta/src/content/apis/react-dom/server/renderToPipeableStream.md +++ b/beta/src/content/apis/react-dom/server/renderToPipeableStream.md @@ -2,22 +2,576 @@ title: renderToPipeableStream --- - + -This section is incomplete, please see the old docs for [renderToPipeableStream.](https://reactjs.org/docs/react-dom-server.html#rendertopipeablestream) +`renderToPipeableStream` renders a React tree to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html) - +```js +const stream = renderToPipeableStream(reactNode, options) +``` + - + + +--- + +## Usage {/*usage*/} + +### Rendering a React tree as HTML to a Node.js Stream {/*rendering-a-react-tree-as-html-to-a-nodejs-stream*/} + +Call `renderToPipeableStream` to render your React tree as HTML into a [Node.js Stream:](https://nodejs.org/api/stream.html#writable-streams) + +```js [[1, 5, ""], [2, 6, "['/main.js']"]] +import { renderToPipeableStream } from 'react-dom/server'; + +// The route handler syntax depends on your backend framework +app.use('/', (request, response) => { + const { pipe } = renderToPipeableStream(, { + bootstrapScripts: ['/main.js'], + onShellReady() { + pipe(response); + } + }); +}); +``` + +Along with the root component, you need to provide a list of boostrap ` +``` + +On the client, your bootstrap script should [hydrate the entire `document` with a call to `hydrateRoot`:](/apis/react-dom/client/hydrateRoot#hydrating-an-entire-document) + +```js [[1, 4, ""]] +import {hydrateRoot} from 'react-dom/client'; +import App from './App.js'; + +hydrateRoot(document, ); +``` + +This will attach event listeners to the server-generated HTML and make it interactive. + + + +#### Reading CSS and JS asset paths from the build output {/*reading-css-and-js-asset-paths-from-the-build-output*/} + +The final asset URLs (like JavaScript and CSS files) are often hashed after the build. For example, instead of `styles.css` you might end up with `styles.123456.css`. Hashing static asset filenames guarantees that every distinct build of the same asset will have a different filename. This is useful because it lets you safely enable long-term caching for static assets: a file with a certain name would never change content. + +However, if you don't know the asset URLs until after the build, there's no way for you to put them in the source code. For example, hardcoding `"/styles.css"` into JSX like earlier wouldn't work. To keep them out of your source code, your root component can read the real filenames from a map passed as a prop: + +```js {1,6} +export default function App({ assetMap }) { + return ( + + + My app + + + ... + + ); +} +``` + +On the server, render `` and pass your `assetMap` with the asset URLs: + +```js {1-5,8} +// You'd need to get this JSON from your build tooling, e.g. read it from the build output. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +app.use('/', (request, response) => { + const { pipe } = renderToPipeableStream(, { + bootstrapScripts: [assetMap['main.js']], + onShellReady() { + pipe(response); + } + }); +}); +``` + +Since your server is now rendering ``, you need to render it with `assetMap` on the client too to avoid hydration errors. You can serialize and pass `assetMap` to the client like this: + +```js {9-10} +// You'd need to get this JSON from your build tooling. +const assetMap = { + 'styles.css': '/styles.123456.css', + 'main.js': '/main.123456.js' +}; + +app.use('/', (request, response) => { + const { pipe } = renderToPipeableStream(, { + // Careful: It's safe to stringify() this because this data isn't user-generated. + bootstrapScriptContents: `window.assetMap = ${JSON.stringify(assetMap)};`, + bootstrapScripts: [assetMap['main.js']], + onShellReady() { + pipe(response); + } + }); +}); +``` + +In the example above, the `bootstrapScriptContents` option adds an extra inline `