Skip to content
2 changes: 1 addition & 1 deletion src/content/reference/react-dom/browser.md
Original file line number Diff line number Diff line change
Expand Up @@ -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*/}

Expand Down
6 changes: 6 additions & 0 deletions src/content/reference/react-dom/client/hydrateRoot.md
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -319,6 +321,10 @@ 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 want the client-rendered content to be different from the initial server-rendered HTML.

<Canary>If a component should render only in the browser, call [`use(browser())`](/reference/react/use#use-browser) instead of waiting for an Effect.</Canary>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note we should probably delete this entire subsection once this ships in stable?


<Pitfall>

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.
Expand Down
8 changes: 6 additions & 2 deletions src/content/reference/react/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ 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.
* <CanaryBadge /> 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).
```js
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
use(browser());
// ...
}
```
4 changes: 3 additions & 1 deletion src/content/reference/react/use.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: use

<Intro>

`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 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);
Expand Down Expand Up @@ -1326,6 +1326,8 @@ async function getData(url) {

---

## Usage (Browser) {/*usage-browser*/}

### <CanaryBadge /> 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.
Expand Down
4 changes: 3 additions & 1 deletion src/content/reference/react/useLayoutEffect.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`<Suspense>`](/reference/react/Suspense) boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering.
- <CanaryBadge /> 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 [`<Suspense>`](/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 `<Suspense>` 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 ? <RealContent /> : <FallbackContent />`. 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.

Expand Down
Loading