From 9a97f419d20eca2d35e09aeb89e2ceda18547419 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Thu, 20 Aug 2026 23:51:59 +0200
Subject: [PATCH 01/18] Add conditional browser query example
---
src/content/reference/react-dom/browser.md | 176 +++++++++++++++++++++
1 file changed, 176 insertions(+)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 017da34e7d2..495f2afeaa7 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -258,6 +258,182 @@ 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.
+This example renders one query with initial data and one without it.
+
+Click **Reload** to see the second product's loading fallback before its query resolves.
+
+
+
+```js src/App.js active
+import { Suspense, use } from 'react';
+import { browser } from 'react-dom';
+import { useQuery } from './query.js';
+
+function useBrowserQuery(query, options) {
+ if (options.initialData === undefined) {
+ use(browser('useBrowserQuery: No initial data was provided.'));
+ }
+ return useQuery(query, options);
+}
+
+function ProductDetails({productId, initialData}) {
+ const product = useBrowserQuery(`/api/products/${productId}`, {
+ initialData,
+ });
+ return {product.name};
+}
+
+export default function App() {
+ return (
+ <>
+ Featured products
+
+ -
+
+
+ Loading another product...}>
+ -
+
+
+
+
+ >
+ );
+}
+```
+
+```js src/query.js hidden
+import { use } from 'react';
+
+// This is a simplified implementation of a
+// Suspense-enabled query library.
+
+const products = {
+ '/api/products/react-shirt': {name: 'React shirt'},
+};
+
+const cache = new Map();
+
+function fetchProduct(query) {
+ if (!cache.has(query)) {
+ cache.set(
+ query,
+ new Promise(resolve => {
+ setTimeout(() => resolve(products[query]), 600);
+ })
+ );
+ }
+ return cache.get(query);
+}
+
+export function useQuery(query, options) {
+ if (options.initialData !== undefined) {
+ return options.initialData;
+ }
+ return use(fetchProduct(query));
+}
+```
+
+```js src/Document.js hidden
+import App from './App.js';
+
+export default function Document() {
+ return (
+
+
+ Featured products
+
+
+
+
+
+
+ );
+}
+```
+
+```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();
+ await flushReadableStreamToFrame(stream, frame);
+
+ // Wait so both the fallback and hydrated content are visible.
+ await new Promise(resolve => setTimeout(resolve, 1200));
+ hydrateRoot(frame.contentDocument, );
+}
+
+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
+
+
+
+
+ Conditional browser rendering
+
+
+
+
+
+```
+
+```css src/styles.css hidden
+iframe {
+ width: 100%;
+ height: 170px;
+ 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"
+ }
+}
+```
+
+
+
---
### Reporting browser-only rendering on the server {/*reporting-browser-only-rendering-on-the-server*/}
From 9247c01776db1e48aee9876685d202c75ca7a952 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 13:12:25 +0200
Subject: [PATCH 02/18] Move browser query hook into its own example file
---
src/content/reference/react-dom/browser.md | 25 +++++++++++++---------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 495f2afeaa7..a08fe807ba6 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -265,16 +265,8 @@ Click **Reload** to see the second product's loading fallback before its query r
```js src/App.js active
-import { Suspense, use } from 'react';
-import { browser } from 'react-dom';
-import { useQuery } from './query.js';
-
-function useBrowserQuery(query, options) {
- if (options.initialData === undefined) {
- use(browser('useBrowserQuery: No initial data was provided.'));
- }
- return useQuery(query, options);
-}
+import { Suspense } from 'react';
+import { useBrowserQuery } from './useBrowserQuery.js';
function ProductDetails({productId, initialData}) {
const product = useBrowserQuery(`/api/products/${productId}`, {
@@ -305,6 +297,19 @@ export default function App() {
}
```
+```js src/useBrowserQuery.js
+import { use } from 'react';
+import { browser } from 'react-dom';
+import { useQuery } from './query.js';
+
+export function useBrowserQuery(query, options) {
+ if (options.initialData === undefined) {
+ use(browser('useBrowserQuery: No initial data was provided.'));
+ }
+ return useQuery(query, options);
+}
+```
+
```js src/query.js hidden
import { use } from 'react';
From 262b84a663fac9000d83cb5e47c5841ba0108e9e Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 19:41:18 +0200
Subject: [PATCH 03/18] Use IndexedDB in conditional browser example
---
src/content/reference/react-dom/browser.md | 125 +++++++++++----------
1 file changed, 63 insertions(+), 62 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index a08fe807ba6..61faee3fd3f 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,60 +236,53 @@ export default function SavedDraft() {
### Conditionally rendering in the browser {/*conditionally-rendering-in-the-browser*/}
-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), you can call `use(browser())` conditionally or inside a custom Hook. For example, a custom Hook can use initial data when it is available during server rendering, and read from IndexedDB in the browser when it isn't:
```js {3}
-function useBrowserQuery(query, options) {
- if (options.initialData === undefined) {
- use(browser('useBrowserQuery: No initial data was provided.'));
+function useDraft(draftId, initialDraft) {
+ if (initialDraft !== undefined) {
+ return initialDraft;
}
- return useQuery(query, options);
-}
-
-function ProductDetails({ productId, initialData }) {
- const product = useBrowserQuery(`/api/products/${productId}`, {
- initialData,
- });
-
- return {product.name}
;
+ use(browser('The draft is stored in IndexedDB.'));
+ return use(readDraft(draftId));
}
```
-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.
+On the server, `useDraft` returns `initialDraft` when it is provided. Otherwise, the closest Suspense boundary's fallback remains in the HTML. In the browser, `use(browser())` returns `undefined`, so the Hook continues and reads the draft from IndexedDB.
-This example renders one query with initial data and one without it.
+This example renders one draft with initial data and one stored in IndexedDB.
-Click **Reload** to see the second product's loading fallback before its query resolves.
+Click **Reload** to see the second draft's loading fallback while React reads it from IndexedDB.
```js src/App.js active
import { Suspense } from 'react';
-import { useBrowserQuery } from './useBrowserQuery.js';
+import { useDraft } from './useDraft.js';
-function ProductDetails({productId, initialData}) {
- const product = useBrowserQuery(`/api/products/${productId}`, {
- initialData,
- });
- return {product.name};
+function Draft({draftId, title, initialDraft}) {
+ const draft = useDraft(draftId, initialDraft);
+ return (
+
+ {title}
+ {draft}
+
+ );
}
export default function App() {
return (
<>
- Featured products
+ Saved drafts
- -
-
-
- Loading another product...}>
- -
-
-
+
+ Loading saved draft...}>
+
>
@@ -297,48 +290,56 @@ export default function App() {
}
```
-```js src/useBrowserQuery.js
+```js src/useDraft.js
import { use } from 'react';
import { browser } from 'react-dom';
-import { useQuery } from './query.js';
+import { readDraft } from './database.js';
-export function useBrowserQuery(query, options) {
- if (options.initialData === undefined) {
- use(browser('useBrowserQuery: No initial data was provided.'));
+export function useDraft(draftId, initialDraft) {
+ if (initialDraft !== undefined) {
+ return initialDraft;
}
- return useQuery(query, options);
+
+ use(browser('The draft is stored in IndexedDB.'));
+ return use(readDraft(draftId));
}
```
-```js src/query.js hidden
-import { use } from 'react';
-
-// This is a simplified implementation of a
-// Suspense-enabled query library.
-
-const products = {
- '/api/products/react-shirt': {name: 'React shirt'},
+```js src/database.js hidden
+const drafts = {
+ 'trip-notes': 'Remember to pack a charger.',
};
const cache = new Map();
-function fetchProduct(query) {
- if (!cache.has(query)) {
- cache.set(
- query,
- new Promise(resolve => {
- setTimeout(() => resolve(products[query]), 600);
- })
- );
+export function readDraft(draftId) {
+ if (!cache.has(draftId)) {
+ cache.set(draftId, readDraftFromIndexedDB(draftId));
}
- return cache.get(query);
+ return cache.get(draftId);
}
-export function useQuery(query, options) {
- if (options.initialData !== undefined) {
- return options.initialData;
- }
- return use(fetchProduct(query));
+function readDraftFromIndexedDB(draftId) {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open('browser-example', 1);
+
+ request.onupgradeneeded = () => {
+ const store = request.result.createObjectStore('drafts');
+ for (const [key, value] of Object.entries(drafts)) {
+ store.add(value, key);
+ }
+ };
+
+ request.onerror = () => reject(request.error);
+ request.onsuccess = () => {
+ const transaction = request.result.transaction('drafts');
+ const draftRequest = transaction.objectStore('drafts').get(draftId);
+ draftRequest.onerror = () => reject(draftRequest.error);
+ draftRequest.onsuccess = () => {
+ setTimeout(() => resolve(draftRequest.result), 600);
+ };
+ };
+ });
}
```
@@ -349,7 +350,7 @@ export default function Document() {
return (
- Featured products
+ Saved drafts
From 4bb86b6e8b4f4a944f55a538f12055c142d0fddf Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 19:49:54 +0200
Subject: [PATCH 04/18] Clarify conditional browser rendering example
---
src/content/reference/react-dom/browser.md | 96 ++++++++++------------
1 file changed, 45 insertions(+), 51 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 61faee3fd3f..9869bbd3fdb 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,37 +236,34 @@ export default function SavedDraft() {
### Conditionally rendering in the browser {/*conditionally-rendering-in-the-browser*/}
-Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally or inside a custom Hook. For example, a custom Hook can use initial data when it is available during server rendering, and read from IndexedDB in the browser when it isn't:
+Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally or inside a custom Hook. For example, a custom Hook can return an initial value when it is provided, and read it from IndexedDB in the browser when it isn't:
-```js {3}
-function useDraft(draftId, initialDraft) {
- if (initialDraft !== undefined) {
- return initialDraft;
+```js {6}
+function useSetting(settingId, initialValue) {
+ if (initialValue !== undefined) {
+ return initialValue;
}
- use(browser('The draft is stored in IndexedDB.'));
- return use(readDraft(draftId));
+ use(browser('No initial setting was provided.'));
+ return use(readSetting(settingId));
}
```
-On the server, `useDraft` returns `initialDraft` when it is provided. Otherwise, the closest Suspense boundary's fallback remains in the HTML. In the browser, `use(browser())` returns `undefined`, so the Hook continues and reads the draft from IndexedDB.
+On the server, `useSetting` returns `initialValue` when it is provided. Otherwise, the closest Suspense boundary's fallback remains in the HTML. In the browser, `use(browser())` returns `undefined`, so the Hook continues and reads the setting from IndexedDB.
-This example renders one draft with initial data and one stored in IndexedDB.
-
-Click **Reload** to see the second draft's loading fallback while React reads it from IndexedDB.
+In this example, the email notification setting is provided as initial data. The push notification setting is not, so click **Reload** to see its loading fallback while React reads it from IndexedDB.
```js src/App.js active
import { Suspense } from 'react';
-import { useDraft } from './useDraft.js';
+import { useSetting } from './useSetting.js';
-function Draft({draftId, title, initialDraft}) {
- const draft = useDraft(draftId, initialDraft);
+function NotificationSetting({settingId, label, initialValue}) {
+ const enabled = useSetting(settingId, initialValue);
return (
- {title}
- {draft}
+ {label}: {enabled ? 'On' : 'Off'}
);
}
@@ -274,15 +271,18 @@ function Draft({draftId, title, initialDraft}) {
export default function App() {
return (
<>
- Saved drafts
+ Notification settings
-
- Loading saved draft...}>
-
+ Loading push notification setting...}>
+
>
@@ -290,53 +290,47 @@ export default function App() {
}
```
-```js src/useDraft.js
+```js src/useSetting.js
import { use } from 'react';
import { browser } from 'react-dom';
-import { readDraft } from './database.js';
+import { readSetting } from './database.js';
-export function useDraft(draftId, initialDraft) {
- if (initialDraft !== undefined) {
- return initialDraft;
+export function useSetting(settingId, initialValue) {
+ if (initialValue !== undefined) {
+ return initialValue;
}
- use(browser('The draft is stored in IndexedDB.'));
- return use(readDraft(draftId));
+ use(browser('No initial setting was provided.'));
+ return use(readSetting(settingId));
}
```
```js src/database.js hidden
-const drafts = {
- 'trip-notes': 'Remember to pack a charger.',
-};
-
const cache = new Map();
-export function readDraft(draftId) {
- if (!cache.has(draftId)) {
- cache.set(draftId, readDraftFromIndexedDB(draftId));
+export function readSetting(settingId) {
+ if (!cache.has(settingId)) {
+ cache.set(settingId, readSettingFromIndexedDB(settingId));
}
- return cache.get(draftId);
+ return cache.get(settingId);
}
-function readDraftFromIndexedDB(draftId) {
+function readSettingFromIndexedDB(settingId) {
return new Promise((resolve, reject) => {
- const request = indexedDB.open('browser-example', 1);
+ const request = indexedDB.open('browser-notification-settings-example', 1);
request.onupgradeneeded = () => {
- const store = request.result.createObjectStore('drafts');
- for (const [key, value] of Object.entries(drafts)) {
- store.add(value, key);
- }
+ const store = request.result.createObjectStore('settings');
+ store.add(true, 'push');
};
request.onerror = () => reject(request.error);
request.onsuccess = () => {
- const transaction = request.result.transaction('drafts');
- const draftRequest = transaction.objectStore('drafts').get(draftId);
- draftRequest.onerror = () => reject(draftRequest.error);
- draftRequest.onsuccess = () => {
- setTimeout(() => resolve(draftRequest.result), 600);
+ const transaction = request.result.transaction('settings');
+ const settingRequest = transaction.objectStore('settings').get(settingId);
+ settingRequest.onerror = () => reject(settingRequest.error);
+ settingRequest.onsuccess = () => {
+ setTimeout(() => resolve(settingRequest.result), 600);
};
};
});
@@ -350,7 +344,7 @@ export default function Document() {
return (
- Saved drafts
+ Notification settings
@@ -417,7 +411,7 @@ export async function flushReadableStreamToFrame(readable, frame) {
```css src/styles.css hidden
iframe {
width: 100%;
- height: 170px;
+ height: 240px;
border: 0;
}
```
From fd80b33b9081dadc6bc9a77c65cd1fde1698280d Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 19:57:02 +0200
Subject: [PATCH 05/18] Polish browser rendering examples
---
src/content/reference/react-dom/browser.md | 31 ++++++++++++++--------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 9869bbd3fdb..6683d8e2002 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,26 +236,33 @@ export default function SavedDraft() {
### Conditionally rendering in the browser {/*conditionally-rendering-in-the-browser*/}
-Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally or inside a custom Hook. For example, a custom Hook can return an initial value when it is provided, and read it from IndexedDB in the browser when it isn't:
+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:
-```js {6}
-function useSetting(settingId, initialValue) {
- if (initialValue !== undefined) {
- return initialValue;
+```js {3}
+function useBrowserQuery(query, options) {
+ if (options.initialData === undefined) {
+ use(browser('useBrowserQuery: No initial data was provided.'));
}
- use(browser('No initial setting was provided.'));
- return use(readSetting(settingId));
+ return useQuery(query, options);
+}
+
+function ProductDetails({ productId, initialData }) {
+ const product = useBrowserQuery(`/api/products/${productId}`, {
+ initialData,
+ });
+
+ return {product.name}
;
}
```
-On the server, `useSetting` returns `initialValue` when it is provided. Otherwise, the closest Suspense boundary's fallback remains in the HTML. In the browser, `use(browser())` returns `undefined`, so the Hook continues and reads the setting from IndexedDB.
+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.
-In this example, the email notification setting is provided as initial data. The push notification setting is not, so click **Reload** to see its loading fallback while React reads it from IndexedDB.
+Here is a complete example using notification settings stored in IndexedDB. The email notification setting receives initial data, but the push notification setting does not. Click **Reload** to see the email setting in the initial HTML while the push setting shows a loading fallback.
-```js src/App.js active
+```js src/App.js
import { Suspense } from 'react';
import { useSetting } from './useSetting.js';
@@ -290,7 +297,7 @@ export default function App() {
}
```
-```js src/useSetting.js
+```js src/useSetting.js active
import { use } from 'react';
import { browser } from 'react-dom';
import { readSetting } from './database.js';
@@ -306,6 +313,8 @@ export function useSetting(settingId, initialValue) {
```
```js src/database.js hidden
+// This is a simplified IndexedDB wrapper for this example.
+
const cache = new Map();
export function readSetting(settingId) {
From 650028b8846209a7fbe5f6f0b9a637d5b6b77534 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 21:59:09 +0200
Subject: [PATCH 06/18] Bridge conditional browser examples
---
src/content/reference/react-dom/browser.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 6683d8e2002..5234b4034dd 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -258,7 +258,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.
-Here is a complete example using notification settings stored in IndexedDB. The email notification setting receives initial data, but the push notification setting does not. Click **Reload** to see the email setting in the initial HTML while the push setting shows a loading fallback.
+Another way to use conditional `use(browser())` is to read from a browser-only data source when initial data is unavailable. In this example, `useSetting` receives an initial value for the email notification setting, so React can include it in the initial HTML. The push notification setting has no initial value, so `useSetting` calls `use(browser())` before reading it from IndexedDB. Click **Reload** to see both paths: the email setting appears immediately, while the push setting shows a loading fallback until `useSetting` reads it from IndexedDB in the browser.
From 44b7dd58ca2c40dceb6eed54ba8a145a3efb36a0 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 22:01:13 +0200
Subject: [PATCH 07/18] Tighten conditional browser example intro
---
src/content/reference/react-dom/browser.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 5234b4034dd..ef7904b6ae1 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -258,7 +258,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.
-Another way to use conditional `use(browser())` is to read from a browser-only data source when initial data is unavailable. In this example, `useSetting` receives an initial value for the email notification setting, so React can include it in the initial HTML. The push notification setting has no initial value, so `useSetting` calls `use(browser())` before reading it from IndexedDB. Click **Reload** to see both paths: the email setting appears immediately, while the push setting shows a loading fallback until `useSetting` reads it from IndexedDB in the browser.
+You can also use this pattern to read from a browser-only data source when initial data isn't available. In this example, the email setting has initial data, but the push setting is read from IndexedDB. Click **Reload** to see the loading fallback for the push setting.
From fa4a59c60a73c18ba8a8e8fbba40481850c1d696 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 24 Aug 2026 22:07:14 +0200
Subject: [PATCH 08/18] Use time zone for conditional browser example
---
src/content/reference/react-dom/browser.md | 85 +++++-----------------
1 file changed, 20 insertions(+), 65 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index ef7904b6ae1..b64bbc4ef05 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -258,91 +258,46 @@ 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.
-You can also use this pattern to read from a browser-only data source when initial data isn't available. In this example, the email setting has initial data, but the push setting is read from IndexedDB. Click **Reload** to see the loading fallback for the push setting.
+You can also call `use(browser())` only when initial data isn't available. In this example, the event time zone is provided as initial data, but the user's time zone is read from the browser. Click **Reload** to see the loading fallback for the user's time zone.
```js src/App.js
import { Suspense } from 'react';
-import { useSetting } from './useSetting.js';
+import { useTimeZone } from './useTimeZone.js';
-function NotificationSetting({settingId, label, initialValue}) {
- const enabled = useSetting(settingId, initialValue);
- return (
-
- {label}: {enabled ? 'On' : 'Off'}
-
- );
+function TimeZone({label, initialTimeZone}) {
+ const timeZone = useTimeZone(initialTimeZone);
+ return {label}: {timeZone}
;
}
export default function App() {
return (
<>
- Notification settings
-
-
- Loading push notification setting...}>
-
-
-
+ Event details
+
+ Loading your time zone...
}>
+
+
>
);
}
```
-```js src/useSetting.js active
+```js src/useTimeZone.js active
import { use } from 'react';
import { browser } from 'react-dom';
-import { readSetting } from './database.js';
-export function useSetting(settingId, initialValue) {
- if (initialValue !== undefined) {
- return initialValue;
+export function useTimeZone(initialTimeZone) {
+ if (initialTimeZone !== undefined) {
+ return initialTimeZone;
}
- use(browser('No initial setting was provided.'));
- return use(readSetting(settingId));
-}
-```
-
-```js src/database.js hidden
-// This is a simplified IndexedDB wrapper for this example.
-
-const cache = new Map();
-
-export function readSetting(settingId) {
- if (!cache.has(settingId)) {
- cache.set(settingId, readSettingFromIndexedDB(settingId));
- }
- return cache.get(settingId);
-}
-
-function readSettingFromIndexedDB(settingId) {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open('browser-notification-settings-example', 1);
-
- request.onupgradeneeded = () => {
- const store = request.result.createObjectStore('settings');
- store.add(true, 'push');
- };
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => {
- const transaction = request.result.transaction('settings');
- const settingRequest = transaction.objectStore('settings').get(settingId);
- settingRequest.onerror = () => reject(settingRequest.error);
- settingRequest.onsuccess = () => {
- setTimeout(() => resolve(settingRequest.result), 600);
- };
- };
- });
+ use(browser('No initial time zone was provided.'));
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
}
```
@@ -353,7 +308,7 @@ export default function Document() {
return (
- Notification settings
+ Event details
From 7574db713b2b88bf8c8a3d94ab11bd783037703f Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Wed, 26 Aug 2026 09:13:25 +0200
Subject: [PATCH 09/18] Clarify conditional example transition
---
src/content/reference/react-dom/browser.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index b64bbc4ef05..418a1d9ae92 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -258,7 +258,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.
-You can also call `use(browser())` only when initial data isn't available. In this example, the event time zone is provided as initial data, but the user's time zone is read from the browser. Click **Reload** to see the loading fallback for the user's time zone.
+The following example uses this pattern with time zones. The event time zone is provided as initial data, while the user's time zone is read from the browser. Click **Reload** to see the loading fallback for the user's time zone.
From 12a44153dbbb585e7c08dffda87a7c8b7e7b285b Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 22:18:42 +0200
Subject: [PATCH 10/18] Lead conditional browser docs with time zone example
---
src/content/reference/react-dom/browser.md | 48 ++++++++++++----------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 418a1d9ae92..5b07810c6bf 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -234,31 +234,13 @@ export default function SavedDraft() {
---
-### Conditionally rendering in the browser {/*conditionally-rendering-in-the-browser*/}
+### Conditionally rendering on the server {/*conditionally-rendering-in-the-browser*/}
-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), you can call `use(browser())` conditionally or inside a custom Hook. For example, a `useTimeZone` Hook can accept an initial time zone when one is available and read it from the device when it is not.
-```js {3}
-function useBrowserQuery(query, options) {
- if (options.initialData === undefined) {
- use(browser('useBrowserQuery: No initial data was provided.'));
- }
+If an initial time zone is provided, `useTimeZone` includes it in the HTML. Otherwise, `use(browser())` leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` returns `undefined`, so `useTimeZone` reads the user's time zone from the device.
- return useQuery(query, options);
-}
-
-function ProductDetails({ productId, initialData }) {
- const product = useBrowserQuery(`/api/products/${productId}`, {
- initialData,
- });
-
- return {product.name}
;
-}
-```
-
-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.
-
-The following example uses this pattern with time zones. The event time zone is provided as initial data, while the user's time zone is read from the browser. Click **Reload** to see the loading fallback for the user's time zone.
+Click **Reload** to see the loading fallback before the user's time zone appears.
@@ -398,6 +380,28 @@ iframe {
+You can apply the same pattern to a Suspense-enabled data-fetching library. For example, a wrapper can call `use(browser())` before the library's `useQuery` when initial data is missing:
+
+```js {3}
+function useBrowserQuery(query, options) {
+ if (options.initialData === undefined) {
+ use(browser('useBrowserQuery: No initial data was provided.'));
+ }
+
+ return useQuery(query, options);
+}
+
+function ProductDetails({ productId, initialData }) {
+ const product = useBrowserQuery(`/api/products/${productId}`, {
+ initialData,
+ });
+
+ return {product.name}
;
+}
+```
+
+During server rendering, `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.
+
---
### Reporting browser-only rendering on the server {/*reporting-browser-only-rendering-on-the-server*/}
From 0749c535b30defbf945e15d8786367fbde259f26 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:03:08 +0200
Subject: [PATCH 11/18] Address conditional browser rendering feedback
---
src/content/reference/react-dom/browser.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 5b07810c6bf..7cc266355d3 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,9 +236,9 @@ export default function SavedDraft() {
### Conditionally rendering on the server {/*conditionally-rendering-in-the-browser*/}
-Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally or inside a custom Hook. For example, a `useTimeZone` Hook can accept an initial time zone when one is available and read it from the device when it is not.
+Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
-If an initial time zone is provided, `useTimeZone` includes it in the HTML. Otherwise, `use(browser())` leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` returns `undefined`, so `useTimeZone` reads the user's time zone from the device.
+For example, `useTimeZone` accepts an optional initial value. If provided, that value is included in the initial HTML and rendered in the browser. If not, `use(browser())` causes the Component calling `useTimeZone` to suspend during server rendering. In the browser, `useTimeZone` reads the device's local time zone.
Click **Reload** to see the loading fallback before the user's time zone appears.
@@ -400,7 +400,7 @@ function ProductDetails({ productId, initialData }) {
}
```
-During server rendering, `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.
+This way, if `initialData` is not provided, `useBrowserQuery` skips server rendering, leaving the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` does not suspend, so the query library can fetch the data or read it from its client cache as usual.
---
From 0e581bde160ee5dda7afe0607f7494f6e7dba5ee Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:21:53 +0200
Subject: [PATCH 12/18] update
---
src/content/reference/react-dom/browser.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 7cc266355d3..5c1d3f3da0d 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -238,7 +238,7 @@ export default function SavedDraft() {
Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
-For example, `useTimeZone` accepts an optional initial value. If provided, that value is included in the initial HTML and rendered in the browser. If not, `use(browser())` causes the Component calling `useTimeZone` to suspend during server rendering. In the browser, `useTimeZone` reads the device's local time zone.
+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. When it is not provided, `use(browser())` suspends the Component during server rendering. In the browser, `use(browser())` does not suspend, so `useTimeZone` returns the device's local time zone.
Click **Reload** to see the loading fallback before the user's time zone appears.
@@ -248,8 +248,8 @@ Click **Reload** to see the loading fallback before the user's time zone appears
import { Suspense } from 'react';
import { useTimeZone } from './useTimeZone.js';
-function TimeZone({label, initialTimeZone}) {
- const timeZone = useTimeZone(initialTimeZone);
+function TimeZone({label, defaultTimeZone}) {
+ const timeZone = useTimeZone(defaultTimeZone);
return {label}: {timeZone}
;
}
@@ -259,7 +259,7 @@ export default function App() {
Event details
Loading your time zone...}>
@@ -273,12 +273,12 @@ export default function App() {
import { use } from 'react';
import { browser } from 'react-dom';
-export function useTimeZone(initialTimeZone) {
- if (initialTimeZone !== undefined) {
- return initialTimeZone;
+export function useTimeZone(defaultTimeZone) {
+ if (defaultTimeZone !== undefined) {
+ return defaultTimeZone;
}
- use(browser('No initial time zone was provided.'));
+ use(browser('No default time zone was provided.'));
return Intl.DateTimeFormat().resolvedOptions().timeZone;
}
```
@@ -400,7 +400,7 @@ function ProductDetails({ productId, initialData }) {
}
```
-This way, if `initialData` is not provided, `useBrowserQuery` skips server rendering, leaving the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` does not suspend, so the query library can fetch the data or read it from its client cache as usual.
+If `initialData` is not provided, `useBrowserQuery` skips server rendering and leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` does not suspend, so the query library can fetch the data or read it from its client cache as usual.
---
From 45720a768f2b3708e3ccfcaed6cdc672e2be5de3 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:30:20 +0200
Subject: [PATCH 13/18] Clarify conditional browser control flow
---
src/content/reference/react-dom/browser.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 5c1d3f3da0d..0c0a8d40ef1 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,9 +236,9 @@ export default function SavedDraft() {
### Conditionally rendering on the server {/*conditionally-rendering-in-the-browser*/}
-Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
+Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. Unlike Hooks, `use` can be called after a conditional return or directly inside a conditional statement. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
-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. When it is not provided, `use(browser())` suspends the Component during server rendering. In the browser, `use(browser())` does not suspend, so `useTimeZone` returns the device's local time zone.
+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. When it is not provided, `use(browser())` suspends the Component during server rendering, but `useTimeZone` returns the device's local time zone when rendering in the browser.
Click **Reload** to see the loading fallback before the user's time zone appears.
@@ -380,7 +380,7 @@ iframe {
-You can apply the same pattern to a Suspense-enabled data-fetching library. For example, a wrapper can call `use(browser())` before the library's `useQuery` when initial data is missing:
+A wrapper around a Suspense-enabled data-fetching library can call `use(browser())` directly inside a condition before the library's `useQuery` when initial data is missing:
```js {3}
function useBrowserQuery(query, options) {
From 0769ce9a101c57f318eeea6bcf9256759c67e959 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:31:35 +0200
Subject: [PATCH 14/18] Clarify conditional data fetching pattern
---
src/content/reference/react-dom/browser.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 0c0a8d40ef1..b638f959520 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -380,7 +380,7 @@ iframe {
-A wrapper around a Suspense-enabled data-fetching library can call `use(browser())` directly inside a condition before the library's `useQuery` when initial data is missing:
+You can apply a similar pattern to conditionally avoid server rendering when using a Suspense-enabled data-fetching library. For example, a wrapper can call `use(browser())` directly inside a condition before the library's `useQuery` when initial data is missing:
```js {3}
function useBrowserQuery(query, options) {
From 20301b3e0c18a55cdf0bf8d85ba8980f092f20b5 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:38:23 +0200
Subject: [PATCH 15/18] Clarify conditional rendering outcomes
---
src/content/reference/react-dom/browser.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index b638f959520..04aef091ec3 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -238,7 +238,7 @@ export default function SavedDraft() {
Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. Unlike Hooks, `use` can be called after a conditional return or directly inside a conditional statement. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
-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. When it is not provided, `use(browser())` suspends the Component during server rendering, but `useTimeZone` returns the device's local time zone when rendering in the browser.
+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.
@@ -400,7 +400,7 @@ function ProductDetails({ productId, initialData }) {
}
```
-If `initialData` is not provided, `useBrowserQuery` skips server rendering and leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `use(browser())` does not suspend, so the query library can fetch the data or read it from its client cache as usual.
+If `initialData` is not provided, `useBrowserQuery` skips server rendering and leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `useBrowserQuery` calls `useQuery`, allowing the query library to fetch the data or read it from its client cache as usual.
---
From 64c6968e7b1b9edab73634d526eee6a7012e07af Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Mon, 31 Aug 2026 23:48:44 +0200
Subject: [PATCH 16/18] Polish conditional browser examples
---
src/content/reference/react-dom/browser.md | 37 ++++++++++++++--------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 04aef091ec3..ebab31cdd23 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,7 +236,9 @@ export default function SavedDraft() {
### Conditionally rendering on the server {/*conditionally-rendering-in-the-browser*/}
-Like other calls to [`use`](/reference/react/use), you can call `use(browser())` conditionally. Unlike Hooks, `use` can be called after a conditional return or directly inside a conditional statement. This lets a Component or custom Hook opt out of server rendering based on a condition, such as the value of a prop passed to it.
+Unlike Hooks, [`use`](/reference/react/use) can be called inside a conditional statement or after an early return.
+
+You can use this behavior with `use(browser())` to conditionally opt a Component out of server rendering, including from inside a custom Hook. The condition might depend on 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.
@@ -400,7 +402,11 @@ function ProductDetails({ productId, initialData }) {
}
```
-If `initialData` is not provided, `useBrowserQuery` skips server rendering and leaves the closest [``](/reference/react/Suspense) boundary's fallback in the HTML. In the browser, `useBrowserQuery` calls `useQuery`, allowing the query library to fetch the data or read it from its client cache as usual.
+When `initialData` is provided, `useBrowserQuery` calls `useQuery` during server rendering, and React includes the rendered content in the HTML.
+
+Without `initialData`, `useBrowserQuery` calls `use(browser())`, suspending the Component and leaving the closest [``](/reference/react/Suspense) boundary's fallback in the HTML.
+
+In the browser, `useBrowserQuery` calls `useQuery` in both cases, allowing the query library to fetch the data or read it from its client cache as usual.
---
@@ -419,19 +425,22 @@ function SavedDraft() {
return ;
}
-const { pipe } = renderToPipeableStream(
- Loading saved draft...}>
-
- ,
- {
- onShellReady() {
- pipe(response);
- },
- onBrowserBailout(error, errorInfo) {
- logBrowserBailout(error, errorInfo);
- }
+function App() {
+ return (
+ Loading saved draft...}>
+
+
+ );
+}
+
+const { pipe } = renderToPipeableStream(, {
+ onShellReady() {
+ pipe(response);
+ },
+ onBrowserBailout(error, errorInfo) {
+ logBrowserBailout(error, errorInfo);
}
-);
+});
```
`onBrowserBailout` receives two arguments:
From 35abef070c43c385777184ae62ae285ae1f7acd0 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Tue, 1 Sep 2026 00:01:08 +0200
Subject: [PATCH 17/18] Clarify conditional query rendering
---
src/content/reference/react-dom/browser.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index ebab31cdd23..5dd0a91af59 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -234,7 +234,7 @@ export default function SavedDraft() {
---
-### Conditionally rendering on the server {/*conditionally-rendering-in-the-browser*/}
+### Conditionally rendering on the server {/*conditionally-rendering-on-the-server*/}
Unlike Hooks, [`use`](/reference/react/use) can be called inside a conditional statement or after an early return.
@@ -402,9 +402,9 @@ function ProductDetails({ productId, initialData }) {
}
```
-When `initialData` is provided, `useBrowserQuery` calls `useQuery` during server rendering, and React includes the rendered content in the HTML.
+When `initialData` is provided, `useBrowserQuery` skips the call to `use(browser())` and passes the initial data to `useQuery`. This lets the Component render on the server.
-Without `initialData`, `useBrowserQuery` calls `use(browser())`, suspending the Component and leaving the closest [``](/reference/react/Suspense) boundary's fallback in the HTML.
+Without `initialData`, `useBrowserQuery` calls `use(browser())`. React leaves the closest [``](/reference/react/Suspense) boundary's fallback in the server-rendered HTML.
In the browser, `useBrowserQuery` calls `useQuery` in both cases, allowing the query library to fetch the data or read it from its client cache as usual.
From a5c9cb214623ce4b270ecaea78d2d78162f253b3 Mon Sep 17 00:00:00 2001
From: Aurora Scharff
Date: Tue, 1 Sep 2026 00:08:57 +0200
Subject: [PATCH 18/18] Align conditional browser guidance
---
src/content/reference/react-dom/browser.md | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md
index 5dd0a91af59..98fa2d465c4 100644
--- a/src/content/reference/react-dom/browser.md
+++ b/src/content/reference/react-dom/browser.md
@@ -236,9 +236,7 @@ export default function SavedDraft() {
### Conditionally rendering on the server {/*conditionally-rendering-on-the-server*/}
-Unlike Hooks, [`use`](/reference/react/use) can be called inside a conditional statement or after an early return.
-
-You can use this behavior with `use(browser())` to conditionally opt a Component out of server rendering, including from inside a custom Hook. The condition might depend on the value of a prop.
+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.
@@ -382,7 +380,7 @@ iframe {
-You can apply a similar pattern to conditionally avoid server rendering when using a Suspense-enabled data-fetching library. For example, a wrapper can call `use(browser())` directly inside a condition before the library's `useQuery` when initial data is missing:
+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) {
@@ -402,11 +400,7 @@ function ProductDetails({ productId, initialData }) {
}
```
-When `initialData` is provided, `useBrowserQuery` skips the call to `use(browser())` and passes the initial data to `useQuery`. This lets the Component render on the server.
-
-Without `initialData`, `useBrowserQuery` calls `use(browser())`. React leaves the closest [``](/reference/react/Suspense) boundary's fallback in the server-rendered HTML.
-
-In the browser, `useBrowserQuery` calls `useQuery` in both cases, allowing the query library to fetch the data or read it from its client cache as usual.
+With `initialData`, React renders the Component to HTML on the server. Without it, React leaves the closest [``](/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.
---