Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 162 additions & 15 deletions src/content/reference/react-dom/browser.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,153 @@ export default function SavedDraft() {

---

### Conditionally rendering in the browser {/*conditionally-rendering-in-the-browser*/}
### Conditionally rendering on the server {/*conditionally-rendering-on-the-server*/}

Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally or inside a custom Hook. For example, you can wrap a Suspense-enabled data-fetching library's `useQuery` and skip server rendering when initial data is missing:
Like other calls to [`use`](/reference/react/use), `use(browser())` can be called inside a conditional statement or after an early return. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop.

For example, this `useTimeZone` Hook accepts an optional default value. When provided, React renders the default value in the initial HTML and in the browser. Without a default value, the Component suspends during server rendering and shows the device's local time zone in the browser.

Click **Reload** to see the loading fallback before the user's time zone appears.

<Sandpack>

```js src/App.js
import { Suspense } from 'react';
import { useTimeZone } from './useTimeZone.js';

function TimeZone({label, defaultTimeZone}) {
const timeZone = useTimeZone(defaultTimeZone);
return <p>{label}: <strong>{timeZone}</strong></p>;
}

export default function App() {
return (
<>
<h1>Event details</h1>
<TimeZone
label="Event time zone"
defaultTimeZone="America/New_York"
/>
<Suspense fallback={<p>Loading your time zone...</p>}>
<TimeZone label="Your time zone" />
</Suspense>
</>
);
}
```

```js src/useTimeZone.js active
import { use } from 'react';
import { browser } from 'react-dom';

export function useTimeZone(defaultTimeZone) {
if (defaultTimeZone !== undefined) {
return defaultTimeZone;
}

use(browser('No default time zone was provided.'));
return Intl.DateTimeFormat().resolvedOptions().timeZone;
}
```

```js src/Document.js hidden
import App from './App.js';

export default function Document() {
return (
<html lang="en">
<head>
<title>Event details</title>
<style>{`
h1 { font-size: 24px; margin-top: 0; }
`}</style>
</head>
<body>
<App />
</body>
</html>
);
}
```

```js src/index.js hidden
import { hydrateRoot } from 'react-dom/client';
import { renderToReadableStream } from 'react-dom/server';
import Document from './Document.js';
import { flushReadableStreamToFrame } from './demo-helpers.js';
import './styles.css';

async function main(frame) {
const stream = await renderToReadableStream(<Document />);
await flushReadableStreamToFrame(stream, frame);

// Wait so both the fallback and hydrated content are visible.
await new Promise(resolve => setTimeout(resolve, 1200));
hydrateRoot(frame.contentDocument, <Document />);
}

main(document.getElementById('preview'));
```

```js src/demo-helpers.js hidden
export async function flushReadableStreamToFrame(readable, frame) {
const doc = frame.contentWindow.document;
const decoder = new TextDecoder();
const reader = readable.getReader();

while (true) {
const {done, value} = await reader.read();
if (done) {
break;
}
doc.write(decoder.decode(value, {stream: true}));
}

doc.write(decoder.decode());
doc.close();
}
```

```html public/index.html hidden
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Conditional browser rendering</title>
</head>
<body>
<iframe id="preview" title="Rendered page"></iframe>
</body>
</html>
```

```css src/styles.css hidden
iframe {
width: 100%;
height: 240px;
border: 0;
}
```

```json package.json hidden
{
"dependencies": {
"react": "19.3.0-canary-eb8feb71-20260814",
"react-dom": "19.3.0-canary-eb8feb71-20260814",
"react-scripts": "latest"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
```

</Sandpack>

You can apply a similar pattern to conditionally avoid server rendering when using a Suspense-enabled data-fetching library:

```js {3}
function useBrowserQuery(query, options) {
Expand All @@ -256,7 +400,7 @@ function ProductDetails({ productId, initialData }) {
}
```

On the server, `useBrowserQuery` calls `useQuery` only when `initialData` is available. Otherwise, the closest Suspense boundary's fallback remains in the HTML. In the browser, `use(browser())` returns `undefined`, so the query library can fetch the data or read it from its client cache.
With `initialData`, React renders the Component to HTML on the server. Without it, React leaves the closest [`<Suspense>`](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `useQuery` can fetch the data or read it from its client cache as usual.

---

Expand All @@ -275,19 +419,22 @@ function SavedDraft() {
return <DraftEditor initialDraft={draft} />;
}

const { pipe } = renderToPipeableStream(
<Suspense fallback={<p>Loading saved draft...</p>}>
<SavedDraft />
</Suspense>,
{
onShellReady() {
pipe(response);
},
onBrowserBailout(error, errorInfo) {
logBrowserBailout(error, errorInfo);
}
function App() {
return (
<Suspense fallback={<p>Loading saved draft...</p>}>
<SavedDraft />
</Suspense>
);
}

const { pipe } = renderToPipeableStream(<App />, {
onShellReady() {
pipe(response);
},
onBrowserBailout(error, errorInfo) {
logBrowserBailout(error, errorInfo);
}
);
});
```

`onBrowserBailout` receives two arguments:
Expand Down
1 change: 1 addition & 0 deletions src/content/reference/react-dom/client/hydrateRoot.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ React will attach to the HTML that exists inside the `domNode`, and take over ma
* **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`.
* **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with the `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`.
* **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/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** `formState`: The form state from a form submission handled by a [Server Function](/reference/rsc/server-functions). If the page was rendered on the server in response to a submission of a form that uses [`useActionState`](/reference/react/useActionState) with a `permalink`, pass the resulting form state so that `useActionState` returns the submitted state instead of the `initialState`. Must be the same value as the `formState` passed to the [server renderer.](/reference/react-dom/server/renderToPipeableStream#parameters) This is typically passed through by your framework.


#### Returns {/*returns*/}
Expand Down
4 changes: 2 additions & 2 deletions src/content/reference/react-dom/server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `react-dom/server` APIs let you server-side render React components to HTML.
These methods are only available in the environments with [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API), which includes browsers, Deno, and some modern edge runtimes:

* [`renderToReadableStream`](/reference/react-dom/server/renderToReadableStream) renders a React tree to a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
* [`resume`](/reference/react-dom/server/renderToPipeableStream) resumes [`prerender`](/reference/react-dom/static/prerender) to a [Readable Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
* [`resume`](/reference/react-dom/server/resume) resumes [`prerender`](/reference/react-dom/static/prerender) to a [Readable Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).


<Note>
Expand All @@ -30,7 +30,7 @@ Node.js also includes these methods for compatibility, but they are not recommen
These methods are only available in the environments with [Node.js Streams:](https://nodejs.org/api/stream.html)

* [`renderToPipeableStream`](/reference/react-dom/server/renderToPipeableStream) renders a React tree to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
* [`resumeToPipeableStream`](/reference/react-dom/server/renderToPipeableStream) resumes [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
* [`resumeToPipeableStream`](/reference/react-dom/server/resumeToPipeableStream) resumes [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)

---

Expand Down
20 changes: 20 additions & 0 deletions src/content/reference/react-dom/server/renderToPipeableStream.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const { pipe } = renderToPipeableStream(<App />, {

* `reactNode`: HTML болгон дүрслэх React node. Жишээлбэл, `<App />` шиг JSX элемент. Энэ нь баримт бичгийг бүхэлд нь төлөөлөх ёстой тул `App` компонент `<html>` tag-ийг дүрслэх хэрэгтэй.

<<<<<<< HEAD
* **optional** `options`: Урсгалын тохиргоонуудыг агуулсан объект.
* **optional** `bootstrapScriptContent`: Заасан тохиолдолд энэ тэмдэгт мөрийг inline `<script>` tag дотор байрлуулна.
* **optional** `bootstrapScripts`: Хуудаст гаргах `<script>` tag-уудын URL тэмдэгт мөрийн массив. [`hydrateRoot`](/reference/react-dom/client/hydrateRoot)-ийг дууддаг `<script>`-ийг оруулахдаа ашиглана. Клиент талд React огт ажиллуулахгүй бол үүнийг орхино.
Expand All @@ -61,6 +62,25 @@ const { pipe } = renderToPipeableStream(<App />, {
* **optional** `onShellReady`: [Анхны shell](#specifying-what-goes-into-the-shell) дүрслэгдмэгц ажиллах callback. Энд [status code тохируулж](#setting-the-status-code), `pipe`-ийг дуудан урсгалыг эхлүүлж болно. Дараа нь React shell-ийн араас [нэмэлт контентыг урсгалаар дамжуулах](#streaming-more-content-as-it-loads) бөгөөд inline `<script>` tag-ууд HTML-ийн ачаалж буй fallback-ийг бэлэн контентоор солино.
* **optional** `onShellError`: Анхны shell-ийг дүрслэхэд алдаа гарвал ажиллах callback. Алдааг аргумент болгон хүлээн авна. Урсгал руу хараахан byte гараагүй, `onShellReady` болон `onAllReady` дуудагдахгүй тул [fallback HTML shell гаргаж болно](#recovering-from-errors-inside-the-shell).
* **optional** `progressiveChunkSize`: Нэг chunk дэх byte-ийн тоо. [Анхдагч heuristic-ийн талаар дэлгэрэнгүй уншина уу.](https://github.com/react/react/blob/14c2be8dac2d5482fda8a0906a31d239df8551fc/packages/react-server/src/ReactFizzServer.js#L210-L225)
=======
* **optional** `options`: An object with streaming options.
* **optional** `bootstrapScriptContent`: If specified, this string will be placed in an inline `<script>` tag.
* **optional** `bootstrapScripts`: An array of string URLs for the `<script>` tags to emit on the page. Use this to include the `<script>` that calls [`hydrateRoot`.](/reference/react-dom/client/hydrateRoot) Omit it if you don't want to run React on the client at all.
* **optional** `bootstrapModules`: Like `bootstrapScripts`, but emits [`<script type="module">`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) instead.
* **optional** `formState`: The form state from a form submission handled by a [Server Function](/reference/rsc/server-functions). If the page is rendered in response to a submission of a form that uses [`useActionState`](/reference/react/useActionState) with a `permalink`, pass the resulting form state so that React embeds it into the HTML for hydration. The same value must be passed to [`hydrateRoot`](/reference/react-dom/client/hydrateRoot#parameters) on the client. This is typically passed through by your framework.
* **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as passed to [`hydrateRoot`.](/reference/react-dom/client/hydrateRoot#parameters)
* **optional** `importMap`: An [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) object with `imports` and `scopes` properties. React emits it as an inline `<script type="importmap">` tag before any module scripts, so that `<script type="module">` tags (for example, from `bootstrapModules`) can use bare module specifiers. <CanaryBadge /> When `nonce` is set, it is also applied to the import map script.
* **optional** `maxHeadersLength`: The maximum total length of the header content passed to `onHeaders`, measured in UTF-16 code units. Defaults to 2000. Once the limit is reached, React stops adding resource hints to the headers.
* **optional** `namespaceURI`: A string with the root [namespace URI](https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS#important_namespace_uris) 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.
* **optional** `nonce`: A [`nonce`](http://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#nonce) string to allow scripts for [`script-src` Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src). To use different nonces for scripts and styles, pass an object with `script` and `style` properties instead.
* **optional** `onAllReady`: A callback that fires when all rendering is complete, including both the [shell](#specifying-what-goes-into-the-shell) and all additional [content.](#streaming-more-content-as-it-loads) You can use this instead of `onShellReady` [for crawlers and static generation.](#waiting-for-all-content-to-load-for-crawlers-and-static-generation) If you start streaming here, you won't get any progressive loading. The stream will contain the final HTML.
* <CanaryBadge /> **optional** `onBrowserBailout`: A callback React calls when it recovers from [`browser()`](/reference/react-dom/browser) by leaving a Suspense fallback for the browser to replace. It receives an `Error` describing the browser-only render and an `errorInfo` object containing the `componentStack`. If a reason was passed to `browser`, it is available as `error.cause`. By default, React does nothing. [See how to report browser-only rendering.](/reference/react-dom/browser#reporting-browser-only-rendering-on-the-server)
* **optional** `onError`: A callback that fires whenever there is a server error, whether [recoverable](#recovering-from-errors-outside-the-shell) or [not.](#recovering-from-errors-inside-the-shell) By default, this only calls `console.error`. If you override it to [log crash reports,](#logging-crashes-on-the-server) make sure that you still call `console.error`. You can also use it to [adjust the status code](#setting-the-status-code) before the shell is emitted.
* **optional** `onHeaders`: A callback that fires when React has determined the resource hints for the document, such as preconnects and stylesheet, font, or high-priority image preloads. It receives an object with a `Link` property containing the corresponding [`Link` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/link) value, so you can send it as an HTTP response header or as a [103 Early Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103) response. React calls it even when there are no resource hints to send. The header content is capped by `maxHeadersLength`.
* **optional** `onShellReady`: A callback that fires right after the [initial shell](#specifying-what-goes-into-the-shell) has been rendered. You can [set the status code](#setting-the-status-code) and call `pipe` here to start streaming. React will [stream the additional content](#streaming-more-content-as-it-loads) after the shell along with the inline `<script>` tags that replace the HTML loading fallbacks with the content.
* **optional** `onShellError`: A callback that fires if there was an error rendering the initial shell. It receives the error as an argument. No bytes were emitted from the stream yet, and neither `onShellReady` nor `onAllReady` will get called, so you can [output a fallback HTML shell.](#recovering-from-errors-inside-the-shell)
* **optional** `progressiveChunkSize`: The number of bytes in a chunk. [Read more about the default heuristic.](https://github.com/react/react/blob/14c2be8dac2d5482fda8a0906a31d239df8551fc/packages/react-server/src/ReactFizzServer.js#L210-L225)
>>>>>>> f3d9794fc31f4a3faf7e863984d37f4ae86b3290


#### Буцаах утга {/*returns*/}
Expand Down
Loading
Loading