A Deep Dive into React’s New Component
Have you ever navigated away from a tab in your app, only to return and find your scroll position lost, your input fields cleared, or a loading spinner greeting you all over again?
Traditionally, React developers have handled “showing and hiding” UI by conditionally mounting or unmounting components:
{isShowingSidebar && <Sidebar />}
While effective, this approach destroys the component state every time it unmounts. In modern React (v19+), there is a better way. Enter the component.
What is the Component?
Formerly known as the “Offscreen” API during its experimental phase, is a built-in React component that allows you to hide and restore UI without losing its internal state or DOM nodes.
Instead of removing elements from the tree, keeps them “alive” in the background but visually hidden.
The Basic Syntax
import { Activity } from 'react';
function App() {
const [isVisible, setIsVisible] = useState(true);
return (
<Activity mode={isVisible ? "visible" : "hidden"}>
<Sidebar />
</Activity>
);
}
Game-Changing Use Cases
1. Preserving “Ephemeral” State
When you hide a component with <Activity>, React doesn’t just keep the JavaScript state; it keeps the DOM state.
Form Drafts: If a user types into a <textarea>, switches tabs, and comes back, their text is still there.
Scroll Position: No more manual “scroll restoration” logic—the browser naturally keeps the scroll position because the element was never removed.
2. Intelligent Pre-rendering
This is where gets powerful. You can render components that the user hasn’t seen yet to make your app feel “instant.”
<Activity mode="hidden">
<SlowComponent />
</Activity>
When a component is inside a hidden Activity boundary:
- React renders it at a lower priority, ensuring it doesn’t block the main thread.
- It fetches data (if using Suspense-enabled sources like use).
- It skips running Effects (like useEffect) until the component actually becomes visible.
3. Faster Initial Hydration
React uses a technique called Selective Hydration. Usually, this is triggered by . However, also signals to React that a piece of UI is independent. This allows React to hydrate your “Active” content first, making the page interactive faster, even if the “Hidden” content is complex.
How does it differ from display: none?
You might be thinking: “Can’t I just use CSS display: none?”
While <Activity> does use display: none under the hood to hide elements, it adds several layers of “React Intelligence”:
Effect Orchestration: When mode=”hidden”, React destroys your useEffect cleanups and only re-runs them when the component becomes visible. This prevents background components from running timers or subscriptions that eat up resources.
Priority Management: Updates inside a hidden <Activity> are deprioritized. React won’t let a background re-render cause a frame drop in your foreground UI.
View Transitions: It integrates with the View Transition API, allowing for smooth animations when content enters or exits.
Important Caveats ⚠️
Ref Behavior: Because the DOM nodes still exist, refs will still point to the hidden elements.
Text Components: If your component returns only text (no wrapper div), won’t render anything when hidden because there is no DOM element to apply display: none to.
Side Effects: If you have side effects that aren’t inside useEffect (like a <video> tag auto-playing), they might continue to run in the background. Always ensure your components are “well-behaved.”
Conclusion
The <Activity> component is a major step toward “Agentic” UI—where our apps are smart enough to prepare content in the background and remember exactly where the user left off.
If you’re building complex dashboards, multi-tab interfaces, or performance-heavy web apps, it’s time to stop unmounting and start using <Activity>.
Are you planning to refactor your tabs to use Activity? Let me know in the comments!
