--- title: --- `` lets you hide and restore the UI and internal state of its children. ```js ``` --- ## Reference {/*reference*/} ### `` {/*activity*/} You can use Activity to hide part of your application: ```js [[1, 1, "\\"hidden\\""], [2, 2, ""], [3, 1, "\\"visible\\""]] ``` When an Activity boundary is hidden, React will visually hide its children using the `display: "none"` CSS property. It will also destroy their Effects, cleaning up any active subscriptions. While hidden, children still re-render in response to new props, albeit at a lower priority than the rest of the content. When the boundary becomes visible again, React will reveal the children with their previous state restored, and re-create their Effects. In this way, Activity can be thought of as a mechanism for rendering "background activity". Rather than completely discarding content that's likely to become visible again, you can use Activity to maintain and restore that content's UI and internal state, while ensuring that your hidden content has no unwanted side effects. [See more examples below.](#usage) #### Props {/*props*/} * `children`: The UI you intend to show and hide. * `mode`: A string value of either `'visible'` or `'hidden'`. If omitted, defaults to `'visible'`. #### Caveats {/*caveats*/} - If an Activity is rendered inside of a [ViewTransition](/reference/react/ViewTransition), and it becomes visible as a result of an update caused by [startTransition](/reference/react/startTransition), it will activate the ViewTransition's `enter` animation. If it becomes hidden, it will activate its `exit` animation. - A *hidden* Activity that just renders text will not render anything rather than rendering hidden text, because thereโ€™s no corresponding DOM element to apply visibility changes to. For example, `` will not produce any output in the DOM for `const ComponentThatJustReturnsText = () => "Hello, World!"`. `` will render visible text. --- ## Usage {/*usage*/} ### Restoring the state of hidden components {/*restoring-the-state-of-hidden-components*/} In React, when you want to conditionally show or hide a component, you typically mount or unmount it based on that condition: ```jsx {isShowingSidebar && ( )} ``` But unmounting a component destroys its internal state, which is not always what you want. When you hide a component using an Activity boundary instead, React will "save" its state for later: ```jsx ``` This makes it possible to hide and then later restore components in the state they were previously in. The following example has a sidebar with an expandable section. You can press "Overview" to reveal the three subitems below it. The main app area also has a button that hides and shows the sidebar. Try expanding the Overview section, and then toggling the sidebar closed then open: ```js src/App.js active import { useState } from 'react'; import Sidebar from './Sidebar.js'; export default function App() { const [isShowingSidebar, setIsShowingSidebar] = useState(true); return ( <> {isShowingSidebar && ( )}

Main content

); } ``` ```js src/Sidebar.js import { useState } from 'react'; export default function Sidebar() { const [isExpanded, setIsExpanded] = useState(false) return ( ); } ``` ```css body { height: 275px; margin: 0; } #root { display: flex; gap: 10px; height: 100%; } nav { padding: 10px; background: #eee; font-size: 14px; height: 100%; } main { padding: 10px; } p { margin: 0; } h1 { margin-top: 10px; } .indicator { margin-left: 4px; display: inline-block; rotate: 90deg; } .indicator.down { rotate: 180deg; } ```
The Overview section always starts out collapsed. Because we unmount the sidebar when `isShowingSidebar` flips to `false`, all its internal state is lost. This is a perfect use case for Activity. We can preserve the internal state of our sidebar, even when visually hiding it. Let's replace the conditional rendering of our sidebar with an Activity boundary: ```jsx {7,9} // Before {isShowingSidebar && ( )} // After ``` and check out the new behavior: ```js src/App.js active import { Activity, useState } from 'react'; import Sidebar from './Sidebar.js'; export default function App() { const [isShowingSidebar, setIsShowingSidebar] = useState(true); return ( <>

Main content

); } ``` ```js src/Sidebar.js import { useState } from 'react'; export default function Sidebar() { const [isExpanded, setIsExpanded] = useState(false) return ( ); } ``` ```css body { height: 275px; margin: 0; } #root { display: flex; gap: 10px; height: 100%; } nav { padding: 10px; background: #eee; font-size: 14px; height: 100%; } main { padding: 10px; } p { margin: 0; } h1 { margin-top: 10px; } .indicator { margin-left: 4px; display: inline-block; rotate: 90deg; } .indicator.down { rotate: 180deg; } ```
Our sidebar's internal state is now restored, without any changes to its implementation. --- ### Restoring the DOM of hidden components {/*restoring-the-dom-of-hidden-components*/} Since Activity boundaries hide their children using `display: none`, their children's DOM is also preserved when hidden. This makes them great for maintaining ephemeral state in parts of the UI that the user is likely to interact with again. In this example, the Contact tab has a `