diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 382bc50b831..017da34e7d2 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -69,24 +69,47 @@ Call `browser` inside `use` in a component that should only render in the browse
You can use this instead of checking `typeof window`, waiting for an [`Effect`](/reference/react/useEffect) to set mounted state, or using a framework option to disable server rendering.
-Press **Render the page**. The loading fallback appears first. After a short delay, React hydrates the page and displays the browser-only editor.
+Click **Reload** to see the loading fallback in the initial HTML. After hydration, React displays the draft loaded from `localStorage`.
```js src/App.js active
-import { Suspense, use } from 'react';
+import { Suspense, use, useState } from 'react';
import { browser } from 'react-dom';
-function BrowserOnlyEditor() {
- use(browser('The editor requires browser APIs.'));
- return ;
+function SavedDraft() {
+ use(browser('The draft is stored in localStorage.'));
+ const [draft, setDraft] = useState(
+ () => localStorage.getItem('draft') ?? ''
+ );
+
+ function handleChange(event) {
+ const nextDraft = event.target.value;
+ setDraft(nextDraft);
+ localStorage.setItem('draft', nextDraft);
+ }
+
+ return (
+
+ );
}
export default function App() {
return (
- Loading editor...
@@ -169,8 +190,8 @@ export async function flushReadableStreamToFrame(readable, frame) {
```css src/styles.css hidden
iframe {
width: 100%;
- height: 180px;
- border: 1px solid #aaa;
+ height: 160px;
+ border: 0;
}
```
@@ -199,12 +220,13 @@ In a React Server Components app, `use(browser())` must be called from a Client
```js {1}
'use client';
-import { use } from 'react';
+import { use, useState } from 'react';
import { browser } from 'react-dom';
-export default function BrowserOnlyEditor() {
- use(browser('The editor requires browser APIs.'));
- return ;
+export default function SavedDraft() {
+ use(browser('The saved draft is stored in localStorage.'));
+ const [draft] = useState(() => localStorage.getItem('draft') ?? '');
+ return ;
}
```
@@ -243,18 +265,19 @@ On the server, `useBrowserQuery` calls `useQuery` only when `initialData` is ava
Pass an `onBrowserBailout` callback to the server renderer to report browser-only rendering. When React leaves a Suspense fallback for the browser, it does not call the server renderer's `onError` callback or [`hydrateRoot`'s `onRecoverableError`](/reference/react-dom/client/hydrateRoot#error-logging-in-production) callback. This example also passes a reason, which is available as the reported error's `cause`:
```js
-import { Suspense, use } from 'react';
+import { Suspense, use, useState } from 'react';
import { browser } from 'react-dom';
import { renderToPipeableStream } from 'react-dom/server';
-function BrowserOnlyEditor() {
- use(browser(() => new Error('The editor requires a browser API.')));
- return ;
+function SavedDraft() {
+ use(browser(() => new Error('The saved draft is stored in localStorage.')));
+ const [draft] = useState(() => localStorage.getItem('draft') ?? '');
+ return ;
}
const { pipe } = renderToPipeableStream(
- Loading editor...}>
-
+ Loading saved draft...}>
+ ,
{
onShellReady() {
diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md
index b4f02633d40..ec62d2424de 100644
--- a/src/content/reference/react/Suspense.md
+++ b/src/content/reference/react/Suspense.md
@@ -2386,24 +2386,47 @@ The server HTML will include the loading indicator. It will be replaced by the `
A Suspense boundary can provide a fallback for a browser-only component. Wrap the component in `` and call [`use(browser())`](/reference/react/use#use-browser) inside it.
-Press **Render the page**. The loading fallback appears first. After a short delay, React hydrates the page and displays the browser-only editor.
+Click **Reload** to see the loading fallback in the initial HTML. After hydration, React displays the draft loaded from `localStorage`.
```js src/App.js active
-import { Suspense, use } from 'react';
+import { Suspense, use, useState } from 'react';
import { browser } from 'react-dom';
-function BrowserOnlyEditor() {
- use(browser('The editor requires browser APIs.'));
- return ;
+function SavedDraft() {
+ use(browser('The draft is stored in localStorage.'));
+ const [draft, setDraft] = useState(
+ () => localStorage.getItem('draft') ?? ''
+ );
+
+ function handleChange(event) {
+ const nextDraft = event.target.value;
+ setDraft(nextDraft);
+ localStorage.setItem('draft', nextDraft);
+ }
+
+ return (
+
+ );
}
export default function App() {
return (
- Loading editor...}>
-
-
+ <>
+
@@ -2486,8 +2507,8 @@ export async function flushReadableStreamToFrame(readable, frame) {
```css src/styles.css hidden
iframe {
width: 100%;
- height: 180px;
- border: 1px solid #aaa;
+ height: 160px;
+ border: 0;
}
```
@@ -2509,7 +2530,7 @@ iframe {
-During server rendering, React includes the Suspense boundary's fallback in the HTML. In the browser, React replaces the fallback with the editor.
+During server rendering, React includes the Suspense boundary's fallback in the HTML. In the browser, React replaces the fallback with the saved draft.
---
diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md
index 9dfbc6ad5a2..26dd8f8309c 100644
--- a/src/content/reference/react/use.md
+++ b/src/content/reference/react/use.md
@@ -1332,24 +1332,47 @@ async function getData(url) {
Pass the value returned by [`browser`](/reference/react-dom/browser) to `use` inside a component that should only render in the browser.
-Press **Render the page**. The loading fallback appears first. After a short delay, React hydrates the page and displays the browser-only editor.
+Click **Reload** to see the loading fallback in the initial HTML. After hydration, React displays the draft loaded from `localStorage`.
```js src/App.js active
-import { Suspense, use } from 'react';
+import { Suspense, use, useState } from 'react';
import { browser } from 'react-dom';
-function BrowserOnlyEditor() {
- use(browser('The editor requires browser APIs.'));
- return ;
+function SavedDraft() {
+ use(browser('The draft is stored in localStorage.'));
+ const [draft, setDraft] = useState(
+ () => localStorage.getItem('draft') ?? ''
+ );
+
+ function handleChange(event) {
+ const nextDraft = event.target.value;
+ setDraft(nextDraft);
+ localStorage.setItem('draft', nextDraft);
+ }
+
+ return (
+
+ );
}
export default function App() {
return (
- Loading editor...}>
-
-
+ <>
+
@@ -1432,8 +1453,8 @@ export async function flushReadableStreamToFrame(readable, frame) {
```css src/styles.css hidden
iframe {
width: 100%;
- height: 180px;
- border: 1px solid #aaa;
+ height: 160px;
+ border: 0;
}
```
@@ -1455,7 +1476,7 @@ iframe {
-During server rendering, `use(browser())` suspends the component and React includes the closest Suspense boundary's fallback in the HTML. In the browser, `use(browser())` returns `undefined` and the editor renders normally.
+During server rendering, `use(browser())` suspends the component and React includes the closest Suspense boundary's fallback in the HTML. In the browser, `use(browser())` returns `undefined` and the saved draft renders normally.
---