Skip to content

Commit 0541585

Browse files
committed
Fix Activity prose width and caveat grouping
1 parent 7e9ff5d commit 0541585

1 file changed

Lines changed: 41 additions & 134 deletions

File tree

‎src/content/reference/react/Activity.md‎

Lines changed: 41 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -38,92 +38,52 @@ import { Activity } from 'react';
3838

3939
An Activity boundary supports two modes:
4040

41-
- In `visible` mode, React renders the children and runs the setup functions for
42-
their `useEffect` and `useLayoutEffect` calls.
43-
- In `hidden` mode, React hides the children and runs the cleanup functions for
44-
their `useEffect` and `useLayoutEffect` calls. React preserves their state and
45-
renders updates at a lower priority than updates to visible content.
41+
- In `visible` mode, React renders the children, attaches their refs, and runs the setup functions for their `useEffect` and `useLayoutEffect` calls.
42+
- In `hidden` mode, React hides the children, detaches their refs, and runs the cleanup functions for their `useEffect` and `useLayoutEffect` calls. React preserves their state and renders updates at a lower priority than updates to visible content.
4643

47-
When a hidden Activity boundary becomes visible, React reveals its children with
48-
their previous state and runs their Effect setup functions again.
44+
When a hidden Activity boundary becomes visible, React reveals its children with their previous state and runs their Effect setup functions again.
4945

50-
In React DOM, hiding an Activity boundary applies `display: none` to the nearest
51-
DOM elements inside the boundary. React preserves those elements while the
52-
boundary remains mounted.
46+
In React DOM, hiding an Activity boundary applies `display: none` to the nearest DOM elements inside the boundary. React preserves those elements while the boundary remains mounted.
47+
48+
Insertion Effects created with [`useInsertionEffect`](/reference/react/useInsertionEffect) remain connected while an Activity boundary is hidden because styles may still be needed by the preserved DOM.
5349

5450
#### Props {/*props*/}
5551

56-
* `children`: The UI rendered by the Activity boundary. `children` can be any
57-
[React node](/reference/react/isValidElement#react-elements-vs-react-nodes).
58-
* **optional** `mode`: Either `'visible'` or `'hidden'`. Defaults to `'visible'`.
59-
See [Modes](#modes) for the behavior of each value.
60-
* **optional** `name`: A string that identifies the Activity boundary in React
61-
Developer Tools.
52+
* `children`: The UI rendered by the Activity boundary. `children` can be any [React node](/reference/react/isValidElement#react-elements-vs-react-nodes).
53+
* **optional** `mode`: Either `'visible'` or `'hidden'`. Defaults to `'visible'`. See [Modes](#modes) for the behavior of each value.
54+
* **optional** `name`: A string that identifies the Activity boundary in React Developer Tools.
6255

6356
#### Caveats {/*caveats*/}
6457

65-
- Hiding an Activity boundary retains its state and DOM nodes, so React does not
66-
reclaim all memory associated with the hidden subtree.
67-
- Browser behavior associated with preserved DOM nodes can continue while the
68-
boundary is hidden. For example, audio and video can continue playing. Use an
69-
Effect cleanup function to stop this behavior.
70-
[See an example below.](#my-hidden-components-have-unwanted-side-effects)
71-
- React runs cleanup functions for Effects created with `useEffect` and
72-
`useLayoutEffect` when an Activity boundary becomes hidden. Insertion Effects
73-
created with
74-
[`useInsertionEffect`](/reference/react/useInsertionEffect)
75-
remain connected because styles may still be needed by the preserved DOM.
76-
- React detaches refs in a hidden Activity boundary and reattaches them when the
77-
boundary becomes visible.
78-
- Content initially rendered inside `<Activity mode="hidden">` is not included in
79-
server-rendered HTML. React renders it on the client at a lower priority after
80-
hydrating visible content.
81-
- React omits text-only output while an Activity boundary is hidden because a text
82-
node cannot receive `display: none`. The text appears when the boundary becomes
83-
visible.
84-
- If an Activity boundary is inside
85-
[`<ViewTransition>`](/reference/react/ViewTransition),
86-
changing it from hidden to visible as part of an update started with
87-
[`startTransition`](/reference/react/startTransition) activates the `enter`
88-
animation. Changing it from visible to hidden as part of that update activates
89-
the `exit` animation.
58+
- Browser behavior associated with preserved DOM nodes can continue while the boundary is hidden. For example, audio and video can continue playing. Use an Effect cleanup function to stop this behavior. [See an example below.](#my-hidden-components-have-unwanted-side-effects)
59+
- React omits text-only output while an Activity boundary is hidden because a text node cannot receive `display: none`. The text appears when the boundary becomes visible.
60+
- If an Activity boundary is inside [`<ViewTransition>`](/reference/react/ViewTransition), changing it from hidden to visible as part of an update started with [`startTransition`](/reference/react/startTransition) activates the `enter` animation. Changing it from visible to hidden as part of that update activates the `exit` animation.
9061

9162
---
9263

9364
## Usage {/*usage*/}
9465

95-
Activity is useful when part of the UI may become hidden and visible again. Unlike
96-
conditional rendering, hiding an Activity boundary preserves both React state and
97-
the DOM state of its children. Unlike hiding content only with CSS, Activity also
98-
cleans up the children's Effects and deprioritizes their updates while they are
99-
hidden.
66+
Activity is useful when part of the UI may become hidden and visible again. Unlike conditional rendering, hiding an Activity boundary preserves both React state and the DOM state of its children. Unlike hiding content only with CSS, Activity also cleans up the children's Effects and deprioritizes their updates while they are hidden.
10067

101-
Use an Activity boundary when preserving that work is valuable—for example, for a
102-
tab the user is likely to revisit or a panel that can prepare data in the
103-
background. If the content is unlikely to become visible again, conditionally
104-
rendering it may be preferable because unmounting allows React and the browser to
105-
release its resources.
68+
Use an Activity boundary when preserving that work is valuable—for example, for a tab the user is likely to revisit or a panel that can prepare data in the background. A hidden boundary retains its state and DOM nodes, so it continues using memory. If the content is unlikely to become visible again, conditionally rendering it may be preferable because unmounting allows React and the browser to release its resources.
10669

10770
### Preserving state while content is hidden {/*restoring-the-state-of-hidden-components*/}
10871

109-
When this condition becomes false, React removes `<Sidebar>` from the tree and
110-
discards its state:
72+
When this condition becomes false, React removes `<Sidebar>` from the tree and discards its state:
11173

11274
```js
11375
{isShowingSidebar && <Sidebar />}
11476
```
11577

116-
Render the component inside an Activity boundary to preserve its state while it is
117-
hidden:
78+
Render the component inside an Activity boundary to preserve its state while it is hidden:
11879

11980
```js
12081
<Activity mode={isShowingSidebar ? 'visible' : 'hidden'}>
12182
<Sidebar />
12283
</Activity>
12384
```
12485

125-
In this example, expand the sidebar, hide it, and show it again. The expanded state
126-
is preserved.
86+
In this example, expand the sidebar, hide it, and show it again. The expanded state is preserved.
12787

12888
<Sandpack>
12989

@@ -208,21 +168,15 @@ main {
208168

209169
</Sandpack>
210170

211-
Changing `mode` preserves the state of the children. Removing the boundary or
212-
changing a child's type, key, or position can
213-
[reset its state](/learn/preserving-and-resetting-state).
171+
Changing `mode` preserves the state of the children. Removing the boundary or changing a child's type, key, or position can [reset its state](/learn/preserving-and-resetting-state).
214172

215173
---
216174

217175
### Preserving DOM state while content is hidden {/*restoring-the-dom-of-hidden-components*/}
218176

219-
An Activity boundary also preserves state held by the browser in DOM nodes. This
220-
includes an uncontrolled input's current value, scroll position, and media
221-
playback position.
177+
An Activity boundary also preserves state held by the browser in DOM nodes. This includes an uncontrolled input's current value, scroll position, and media playback position.
222178

223-
In this example, enter a draft in the Contact section, switch sections, and then
224-
return to Contact. The `<textarea>` value remains because its DOM node was hidden
225-
rather than removed.
179+
In this example, enter a draft in the Contact section, switch sections, and then return to Contact. The `<textarea>` value remains because its DOM node was hidden rather than removed.
226180

227181
<Sandpack>
228182

@@ -306,18 +260,13 @@ textarea {
306260

307261
</Sandpack>
308262

309-
Preserving DOM state also means that DOM behavior can continue while content is
310-
hidden. See [Troubleshooting](#my-hidden-components-have-unwanted-side-effects)
311-
for DOM behavior that requires explicit cleanup.
263+
Preserving DOM state also means that DOM behavior can continue while content is hidden. See [Troubleshooting](#my-hidden-components-have-unwanted-side-effects) for DOM behavior that requires explicit cleanup.
312264

313265
---
314266

315267
### Pre-rendering content that is likely to become visible {/*pre-rendering-content-thats-likely-to-become-visible*/}
316268

317-
An Activity boundary can also prepare content before the user sees it. Content
318-
inside a hidden boundary renders at a lower priority without running Effects
319-
created with `useEffect` or `useLayoutEffect`. This lets the content load code and
320-
render-time data without delaying updates to visible content:
269+
An Activity boundary can also prepare content before the user sees it. Content inside a hidden boundary renders at a lower priority without running Effects created with `useEffect` or `useLayoutEffect`. This lets the content load code and render-time data without delaying updates to visible content:
321270

322271
```js
323272
<Suspense fallback={<Loading />}>
@@ -327,13 +276,9 @@ render-time data without delaying updates to visible content:
327276
</Suspense>
328277
```
329278

330-
If `Posts` suspends while reading code or data, React continues rendering the rest
331-
of the page. If that hidden work completes, switching to the Posts tab can reveal
332-
the content without waiting for the same work again.
279+
If `Posts` suspends while reading code or data, React continues rendering the rest of the page. If that hidden work completes, switching to the Posts tab can reveal the content without waiting for the same work again.
333280

334-
The following example renders the Posts tab in a hidden Activity boundary when the
335-
page first loads. Wait briefly before selecting **Posts**. The list is available
336-
immediately because the hidden render started loading it in the background.
281+
The following example renders the Posts tab in a hidden Activity boundary when the page first loads. Wait briefly before selecting **Posts**. The list is available immediately because the hidden render started loading it in the background.
337282

338283
<Sandpack>
339284

@@ -423,31 +368,21 @@ button {
423368

424369
</Sandpack>
425370

426-
If the user selects Posts before the hidden render finishes, the nearest Suspense
427-
fallback appears until the data is ready. Activity improves the likely case where
428-
the background work finishes first; it does not guarantee that the content will
429-
always be ready.
371+
If the user selects Posts before the hidden render finishes, the nearest Suspense fallback appears until the data is ready. Activity improves the likely case where the background work finishes first; it does not guarantee that the content will always be ready.
430372

431373
<Note>
432374

433-
Only code and data read during rendering can load during pre-rendering. Activity
434-
does not run Effects in hidden content, so data fetched inside an Effect does not
435-
load until the boundary becomes visible.
375+
Only code and data read during rendering can load during pre-rendering. Activity does not run Effects in hidden content, so data fetched inside an Effect does not load until the boundary becomes visible.
436376

437-
The data source must integrate with Suspense. For example, the component can read a
438-
cached Promise with [`use`](/reference/react/use). See
439-
[what activates a Suspense boundary](/reference/react/Suspense#what-activates-a-suspense-boundary).
377+
The data source must integrate with Suspense. For example, the component can read a cached Promise with [`use`](/reference/react/use). See [what activates a Suspense boundary](/reference/react/Suspense#what-activates-a-suspense-boundary).
440378

441379
</Note>
442380

443381
---
444382

445383
### Improving hydration performance {/*speeding-up-interactions-during-page-load*/}
446384

447-
Activity boundaries also divide server-rendered pages into units that React can
448-
hydrate independently. This is related to the selective hydration behavior of
449-
[`<Suspense>`](/reference/react/Suspense), but it does not require displaying a
450-
fallback in the initial UI.
385+
Activity boundaries also divide server-rendered pages into units that React can hydrate independently. This is related to the selective hydration behavior of [`<Suspense>`](/reference/react/Suspense), but it does not require displaying a fallback in the initial UI.
451386

452387
For example, without a boundary React hydrates this page as one unit:
453388

@@ -462,8 +397,7 @@ function Page() {
462397
}
463398
```
464399

465-
Wrapping `Comments` in an always-visible Activity boundary creates a separate
466-
hydration unit:
400+
Wrapping `Comments` in an always-visible Activity boundary creates a separate hydration unit:
467401

468402
```js
469403
function Page() {
@@ -478,10 +412,7 @@ function Page() {
478412
}
479413
```
480414

481-
The boundary is visible because the `mode` prop defaults to `'visible'`. Its
482-
server-rendered HTML remains visible, but React can hydrate it independently from
483-
the surrounding page. If the user interacts with that content before React reaches
484-
it, React prioritizes hydrating the boundary.
415+
The boundary is visible because the `mode` prop defaults to `'visible'`. Its server-rendered HTML remains visible, but React can hydrate it independently from the surrounding page. If the user interacts with that content before React reaches it, React prioritizes hydrating the boundary.
485416

486417
You can also use visible and hidden Activity boundaries for tabbed content:
487418

@@ -509,34 +440,23 @@ function Page() {
509440
}
510441
```
511442

512-
React does not include initially hidden `<Activity>` content in server-rendered HTML.
513-
On the client, React hydrates the visible content first and renders the hidden
514-
content later at a lower priority. Initially visible boundaries are included in the
515-
server-rendered HTML and can be hydrated independently. This allows the visible tab
516-
and the controls around it to become interactive without waiting for React to
517-
render the initially hidden tab.
443+
React does not include initially hidden `<Activity>` content in server-rendered HTML. On the client, React hydrates the visible content first and renders the hidden content later at a lower priority. Initially visible boundaries are included in the server-rendered HTML and can be hydrated independently. This allows the visible tab and the controls around it to become interactive without waiting for React to render the initially hidden tab.
518444

519445
---
520446

521447
## Troubleshooting {/*troubleshooting*/}
522448

523449
### My hidden components have unwanted side effects {/*my-hidden-components-have-unwanted-side-effects*/}
524450

525-
`<Activity>` hides DOM nodes without removing them. Browser-managed behavior from
526-
elements such as `<video>`, `<audio>`, and `<iframe>` can therefore continue while
527-
the boundary is hidden.
451+
`<Activity>` hides DOM nodes without removing them. Browser-managed behavior from elements such as `<video>`, `<audio>`, and `<iframe>` can therefore continue while the boundary is hidden.
528452

529453
<Pitfall>
530454

531455
##### Preserved media can continue playing {/*preserved-media-can-continue-playing*/}
532456

533-
Unmounting a `<video>` element stops playback because the browser removes the DOM
534-
node. Hiding it with Activity preserves the node, so playback continues unless the
535-
component pauses it explicitly.
457+
Unmounting a `<video>` element stops playback because the browser removes the DOM node. Hiding it with Activity preserves the node, so playback continues unless the component pauses it explicitly.
536458

537-
Add the corresponding cleanup to an Effect. For behavior that must stop at the
538-
same time React hides the boundary, use
539-
[`useLayoutEffect`](/reference/react/useLayoutEffect):
459+
Add the corresponding cleanup to an Effect. For behavior that must stop at the same time React hides the boundary, use [`useLayoutEffect`](/reference/react/useLayoutEffect):
540460

541461
```js
542462
import { useLayoutEffect, useRef } from 'react';
@@ -556,17 +476,11 @@ function VideoPlayer({ src }) {
556476
}
557477
```
558478

559-
React runs the cleanup when an enclosing Activity boundary becomes hidden. Because
560-
the `<video>` node remains in the DOM, its playback position is preserved for when
561-
the boundary becomes visible again.
479+
React runs the cleanup when an enclosing Activity boundary becomes hidden. Because the `<video>` node remains in the DOM, its playback position is preserved for when the boundary becomes visible again.
562480

563-
The `useLayoutEffect` cleanup runs as part of hiding the UI. A cleanup from
564-
`useEffect` can run later if, for example, a Suspense boundary suspends or a View
565-
Transition is in progress.
481+
The `useLayoutEffect` cleanup runs as part of hiding the UI. A cleanup from `useEffect` can run later if, for example, a Suspense boundary suspends or a View Transition is in progress.
566482

567-
This complete example pauses the video when you switch to Home while preserving
568-
its playback position. When you return to Video, playback can continue from the
569-
same position without recreating the element or downloading it again.
483+
This complete example pauses the video when you switch to Home while preserving its playback position. When you return to Video, playback can continue from the same position without recreating the element or downloading it again.
570484

571485
<Sandpack>
572486

@@ -651,16 +565,11 @@ video {
651565

652566
### My hidden components have Effects that are not running {/*my-hidden-components-have-effects-that-arent-running*/}
653567

654-
React runs cleanup functions for Effects created with `useEffect` and
655-
`useLayoutEffect` when an Activity boundary becomes hidden. It runs their setup
656-
functions again when the boundary becomes visible.
568+
React runs cleanup functions for Effects created with `useEffect` and `useLayoutEffect` when an Activity boundary becomes hidden. It runs their setup functions again when the boundary becomes visible.
657569

658-
An Effect inside a hidden Activity boundary cannot remain active. Move ongoing
659-
work that must continue while the UI is hidden to a component outside the boundary,
660-
or keep the boundary visible.
570+
An Effect inside a hidden Activity boundary cannot remain active. Move ongoing work that must continue while the UI is hidden to a component outside the boundary, or keep the boundary visible.
661571

662-
If an Effect controls an external system, return a cleanup function so hiding the
663-
boundary disconnects from that system:
572+
If an Effect controls an external system, return a cleanup function so hiding the boundary disconnects from that system:
664573

665574
```js
666575
useEffect(() => {
@@ -673,6 +582,4 @@ useEffect(() => {
673582
}, []);
674583
```
675584

676-
Use [`<StrictMode>`](/reference/react/StrictMode) to find Effects that do not clean
677-
up correctly. Strict Mode performs an additional setup and cleanup cycle in
678-
development.
585+
Use [`<StrictMode>`](/reference/react/StrictMode) to find Effects that do not clean up correctly. Strict Mode performs an additional setup and cleanup cycle in development.

0 commit comments

Comments
 (0)