From b14b97aa1b7baa4d94d7471865c608d9f59f8745 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 20:24:23 +0200 Subject: [PATCH 01/11] Clarify browser-only rendering guidance --- src/content/reference/react-dom/client/hydrateRoot.md | 2 ++ src/content/reference/react/Suspense.md | 2 ++ src/content/reference/react/apis.md | 2 +- src/content/reference/react/use.md | 4 +++- src/content/reference/react/useLayoutEffect.md | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index c48b6eb5196..dd94e8c5801 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -319,6 +319,8 @@ export default function App() { This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. +This approach is useful when you need different content on the server and in the browser. If a component should not render on the server at all, React Canary's [`browser`](/reference/react-dom/browser) API lets you mark it as browser-only without waiting for an Effect. + This approach makes hydration slower because your components have to render twice. Be mindful of the user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so rendering a different UI immediately after hydration may also feel jarring to the user. diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 7a2d161ed2d..dca672f1b27 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -2372,6 +2372,8 @@ function Chat() { The server HTML will include the loading indicator. It will be replaced by the `Chat` component on the client. +In React Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error to mark a component as browser-only. + --- ### Providing a fallback for browser-only content {/*providing-a-fallback-for-browser-only-content*/} diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 51438ad9b25..13642f5257f 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -27,7 +27,7 @@ In addition to [Hooks](/reference/react/hooks) and [Components](/reference/react To read a value from a resource, use this API: -* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). +* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass it the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { const message = use(messagePromise); diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index bd58401e71d..949b6a62c84 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,7 +4,7 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). +`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js const value = use(resource); @@ -1326,6 +1326,8 @@ async function getData(url) { --- +## Usage (`browser`) {/*usage-browser*/} + ### Rendering a component only in the browser {/*rendering-a-component-only-in-the-browser*/} Pass the value returned by [`browser`](/reference/react-dom/browser) to `use` inside a component that should only render in the browser. diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 79263b8e7e1..b3962ce5472 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -734,7 +734,7 @@ However, if you're running into this problem, you have a few different options: - Replace `useLayoutEffect` with [`useEffect`.](/reference/react/useEffect) This tells React that it's okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs). -- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. +- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. In React Canary, use the [`browser`](/reference/react-dom/browser) API instead of throwing an error to mark the component as browser-only. - Alternatively, you can render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. From 166fd5b504c1880c95af9562eec652b992cb3168 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 20:31:21 +0200 Subject: [PATCH 02/11] Polish browser-only guidance wording --- src/content/reference/react-dom/client/hydrateRoot.md | 2 +- src/content/reference/react/Suspense.md | 2 +- src/content/reference/react/apis.md | 2 +- src/content/reference/react/use.md | 4 +++- src/content/reference/react/useLayoutEffect.md | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index dd94e8c5801..0aa58eabda7 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -319,7 +319,7 @@ export default function App() { This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. -This approach is useful when you need different content on the server and in the browser. If a component should not render on the server at all, React Canary's [`browser`](/reference/react-dom/browser) API lets you mark it as browser-only without waiting for an Effect. +Use this approach when you need to render different content on the server and in the browser. If a component should render only in the browser, call [`use(browser())`](/reference/react/use#use-browser) in Canary instead of waiting for an Effect. diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index dca672f1b27..76968d8e8ae 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -2372,7 +2372,7 @@ function Chat() { The server HTML will include the loading indicator. It will be replaced by the `Chat` component on the client. -In React Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error to mark a component as browser-only. +If you're using Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error to mark a component as browser-only. --- diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 13642f5257f..de32d77c4f1 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -27,7 +27,7 @@ In addition to [Hooks](/reference/react/hooks) and [Components](/reference/react To read a value from a resource, use this API: -* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass it the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, [`use(browser())`](/reference/react/use#use-browser) marks a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { const message = use(messagePromise); diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 949b6a62c84..eee91d84ca8 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,7 +4,9 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). + +You can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js const value = use(resource); diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index b3962ce5472..02ba5d5f8d2 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -734,7 +734,7 @@ However, if you're running into this problem, you have a few different options: - Replace `useLayoutEffect` with [`useEffect`.](/reference/react/useEffect) This tells React that it's okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs). -- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. In React Canary, use the [`browser`](/reference/react-dom/browser) API instead of throwing an error to mark the component as browser-only. +- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. If you're using Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error. - Alternatively, you can render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. From c2310485968e6ad42c605f28a7c733f37409e927 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 20:33:31 +0200 Subject: [PATCH 03/11] Use Canary markers in browser guidance --- src/content/reference/react-dom/client/hydrateRoot.md | 4 +++- src/content/reference/react/Suspense.md | 2 -- src/content/reference/react/apis.md | 3 ++- src/content/reference/react/useLayoutEffect.md | 4 +++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 0aa58eabda7..54125227f7f 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -319,7 +319,9 @@ export default function App() { This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. -Use this approach when you need to render different content on the server and in the browser. If a component should render only in the browser, call [`use(browser())`](/reference/react/use#use-browser) in Canary instead of waiting for an Effect. +Use this approach when you need to render different content on the server and in the browser. + +If a component should render only in the browser, call [`use(browser())`](/reference/react/use#use-browser) instead of waiting for an Effect. diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 76968d8e8ae..7a2d161ed2d 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -2372,8 +2372,6 @@ function Chat() { The server HTML will include the loading indicator. It will be replaced by the `Chat` component on the client. -If you're using Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error to mark a component as browser-only. - --- ### Providing a fallback for browser-only content {/*providing-a-fallback-for-browser-only-content*/} diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index de32d77c4f1..78fd5b513c9 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -27,7 +27,8 @@ In addition to [Hooks](/reference/react/hooks) and [Components](/reference/react To read a value from a resource, use this API: -* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, [`use(browser())`](/reference/react/use#use-browser) marks a component as browser-only during server rendering. +* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). +* [`use(browser())`](/reference/react/use#use-browser) marks a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { const message = use(messagePromise); diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 02ba5d5f8d2..84f9bc9ef5b 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -734,7 +734,9 @@ However, if you're running into this problem, you have a few different options: - Replace `useLayoutEffect` with [`useEffect`.](/reference/react/useEffect) This tells React that it's okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs). -- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. If you're using Canary, call [`use(browser())`](/reference/react/use#use-browser) instead of throwing an error. +- Alternatively, call [`use(browser())`](/reference/react/use#use-browser) to mark the component as browser-only. React will replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. + +- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. - Alternatively, you can render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. From 17351729e6f9b9afaa40db2e302dbf2b0a780d4b Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 20:41:27 +0200 Subject: [PATCH 04/11] Present browser as a use resource --- src/content/reference/react/apis.md | 13 ++++++++++--- src/content/reference/react/use.md | 4 +--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 78fd5b513c9..458d137a802 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -25,14 +25,21 @@ In addition to [Hooks](/reference/react/hooks) and [Components](/reference/react *Resources* can be accessed by a component without having them as part of their state. For example, a component can read a message from a Promise or read styling information from a context. -To read a value from a resource, use this API: +You can pass these types of resources to [`use`](/reference/react/use): + +* A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to read its resolved value. +* A [context](/learn/passing-data-deeply-with-context) to read its value. +* The value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. -* [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). -* [`use(browser())`](/reference/react/use#use-browser) marks a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { const message = use(messagePromise); const theme = use(ThemeContext); // ... } + +function BrowserOnlyComponent() { + use(browser()); + // ... +} ``` diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index eee91d84ca8..949b6a62c84 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,9 +4,7 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). - -You can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js const value = use(resource); From 87a2fc976cf50ed047d6fb9b13cb313e66770e7b Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 20:43:48 +0200 Subject: [PATCH 05/11] Polish browser usage labels --- src/content/reference/react/use.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 949b6a62c84..34fd9228a93 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,7 +4,7 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). In Canary, you can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). You can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js const value = use(resource); @@ -1326,7 +1326,7 @@ async function getData(url) { --- -## Usage (`browser`) {/*usage-browser*/} +## Usage (Browser) {/*usage-browser*/} ### Rendering a component only in the browser {/*rendering-a-component-only-in-the-browser*/} From cbdd1134a422eefeada81269e6d8d0580b0fbfc2 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:01:34 +0200 Subject: [PATCH 06/11] Address browser guidance review --- src/content/reference/react-dom/client/hydrateRoot.md | 2 +- src/content/reference/react/apis.md | 4 ---- src/content/reference/react/useLayoutEffect.md | 6 +++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 54125227f7f..26974349c5b 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -319,7 +319,7 @@ export default function App() { This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. -Use this approach when you need to render different content on the server and in the browser. +Use this approach when you want the client-rendered content to be different from the initial server-rendered HTML. If a component should render only in the browser, call [`use(browser())`](/reference/react/use#use-browser) instead of waiting for an Effect. diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 458d137a802..892f47bfdbb 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -35,10 +35,6 @@ You can pass these types of resources to [`use`](/reference/react/use): function MessageComponent({ messagePromise }) { const message = use(messagePromise); const theme = use(ThemeContext); - // ... -} - -function BrowserOnlyComponent() { use(browser()); // ... } diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 84f9bc9ef5b..2a33562f697 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -734,10 +734,10 @@ However, if you're running into this problem, you have a few different options: - Replace `useLayoutEffect` with [`useEffect`.](/reference/react/useEffect) This tells React that it's okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs). -- Alternatively, call [`use(browser())`](/reference/react/use#use-browser) to mark the component as browser-only. React will replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. +- Call [`use(browser())`](/reference/react/use#use-browser) to mark the component as browser-only. React will replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. -- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. +- [Mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. -- Alternatively, you can render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. +- Render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. - If you synchronize your component with an external data store and rely on `useLayoutEffect` for different reasons than measuring layout, consider [`useSyncExternalStore`](/reference/react/useSyncExternalStore) instead which [supports server rendering.](/reference/react/useSyncExternalStore#adding-support-for-server-rendering) From b15897f88f22d87d7cd24c4bd53aa855b26d2c74 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:05:43 +0200 Subject: [PATCH 07/11] Clarify browser return value is opaque --- src/content/reference/react-dom/browser.md | 2 +- src/content/reference/react/apis.md | 2 +- src/content/reference/react/use.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/reference/react-dom/browser.md b/src/content/reference/react-dom/browser.md index 11f787d2c9a..7ded671180d 100644 --- a/src/content/reference/react-dom/browser.md +++ b/src/content/reference/react-dom/browser.md @@ -51,7 +51,7 @@ During server rendering, `use(browser())` stops rendering the component and leav #### Returns {/*returns*/} -`browser` returns a value that you can pass to `use` in a component or use as the reason when [aborting a server render](#aborting-pending-server-rendering-for-the-browser). In the browser, passing this value to `use` returns `undefined`. +`browser` returns an opaque value that you can pass to `use` in a component or use as the reason when [aborting a server render](#aborting-pending-server-rendering-for-the-browser). In the browser, passing this value to `use` returns `undefined`. #### Caveats {/*caveats*/} diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 892f47bfdbb..c56e67d5a81 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -29,7 +29,7 @@ You can pass these types of resources to [`use`](/reference/react/use): * A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to read its resolved value. * A [context](/learn/passing-data-deeply-with-context) to read its value. -* The value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +* An opaque value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 34fd9228a93..20b31e9809a 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,7 +4,7 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). You can also pass `use` the value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). You can also call `use` with the opaque value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js const value = use(resource); @@ -100,7 +100,7 @@ During server rendering, the component calling `use(browser())` suspends and Rea #### Parameters {/*browser-parameters*/} -* `browserValue`: The value returned by [`browser`](/reference/react-dom/browser). +* `browserValue`: The opaque value returned by [`browser`](/reference/react-dom/browser). #### Returns {/*browser-returns*/} From 0aff45b1b25f70980c9f35cdb353cb39a5fd3f87 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:07:04 +0200 Subject: [PATCH 08/11] Restore alternative wording --- src/content/reference/react/useLayoutEffect.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 2a33562f697..b9a85d97ce1 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -734,9 +734,9 @@ However, if you're running into this problem, you have a few different options: - Replace `useLayoutEffect` with [`useEffect`.](/reference/react/useEffect) This tells React that it's okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs). -- Call [`use(browser())`](/reference/react/use#use-browser) to mark the component as browser-only. React will replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. +- Alternatively, call [`use(browser())`](/reference/react/use#use-browser) to mark the component as browser-only. React will replace its content up to the closest [``](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering. -- [Mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. +- Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. - Render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. From 49d6af9043ce9f22358410deb10276536fe0cc8c Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:08:19 +0200 Subject: [PATCH 09/11] Restore hydration alternative wording --- src/content/reference/react/useLayoutEffect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index b9a85d97ce1..84f9bc9ef5b 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -738,6 +738,6 @@ However, if you're running into this problem, you have a few different options: - Alternatively, [mark your component as client-only.](/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content) This tells React to replace its content up to the closest `` boundary with a loading fallback during server rendering. -- Render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. +- Alternatively, you can render a component with `useLayoutEffect` only after hydration. Keep a boolean `isMounted` state that's initialized to `false`, and set it to `true` inside a `useEffect` call. Your rendering logic can then be like `return isMounted ? : `. On the server and during the hydration, the user will see `FallbackContent` which should not call `useLayoutEffect`. Then React will replace it with `RealContent` which runs on the client only and can include `useLayoutEffect` calls. - If you synchronize your component with an external data store and rely on `useLayoutEffect` for different reasons than measuring layout, consider [`useSyncExternalStore`](/reference/react/useSyncExternalStore) instead which [supports server rendering.](/reference/react/useSyncExternalStore#adding-support-for-server-rendering) From a47dac669e4873a4b7825af3a0f7debd24ed8b3e Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:52:03 +0200 Subject: [PATCH 10/11] Focus use introduction on resources --- src/content/reference/react/apis.md | 2 +- src/content/reference/react/use.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index c56e67d5a81..892f47bfdbb 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -29,7 +29,7 @@ You can pass these types of resources to [`use`](/reference/react/use): * A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to read its resolved value. * A [context](/learn/passing-data-deeply-with-context) to read its value. -* An opaque value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +* The value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. ```js function MessageComponent({ messagePromise }) { diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 20b31e9809a..a3bce6fd80d 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,7 +4,7 @@ title: use -`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). You can also call `use` with the opaque value returned by [`browser`](/reference/react-dom/browser) to mark a component as browser-only during server rendering. +`use` is a React API that lets you read a resource during rendering, such as a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). ```js const value = use(resource); @@ -100,7 +100,7 @@ During server rendering, the component calling `use(browser())` suspends and Rea #### Parameters {/*browser-parameters*/} -* `browserValue`: The opaque value returned by [`browser`](/reference/react-dom/browser). +* `browserValue`: The value returned by [`browser`](/reference/react-dom/browser). #### Returns {/*browser-returns*/} From 673e3aae5df327ab613e28b4858088b4ec1e1329 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 19 Aug 2026 21:54:48 +0200 Subject: [PATCH 11/11] Note stable browser cleanup --- src/content/reference/react-dom/client/hydrateRoot.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 26974349c5b..bb4a334eb3b 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -274,6 +274,8 @@ This only works one level deep, and is intended to be an escape hatch. Don’t o --- +{/* TODO: Remove this subsection when browser is available in Stable. */} + ### Handling different client and server content {/*handling-different-client-and-server-content*/} If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/reference/react/useState) like `isClient`, which you can set to `true` in an [Effect](/reference/react/useEffect):