Why does the web have amnesia?
You scroll down a Twitter feed. You click a profile. You click "Back". The feed reloads. You lose your spot. You scream.
Native apps don't do this. React apps shouldn't either.
The Problem: In React, when you unmount a component (like when switching tabs), its state is destroyed. To keep it, you have to lift state up, use global stores, or hidden CSS tricks. It's tedious.
The Solution: The <Activity> component (previously known as Offscreen) allows you to "deactivate" a part of the tree without unmounting it. It's like minimizing a window instead of closing it.
02. Meet <Activity />
import { Activity } from 'react';
function App() {
const [mode, setMode] = useState('feed');
return (
<div>
{/*
Instead of {mode === 'feed' && }, which destroys state,
we use Activity to keep it alive in the background.
*/}
<Activity mode={mode === 'feed' ? 'visible' : 'hidden'}>
<Feed />
</Activity>
<Activity mode={mode === 'profile' ? 'visible' : 'hidden'}>
<Profile />
</Activity>
</div>
);
}
03. How It Works: Deprioritization
When an Activity is hidden:
- State is preserved:
useState,useReducer, and DOM state (mostly) stick around. - Rendering stops: It stops receiving updates. It goes dormant.
- Low Priority: React treats it as low priority. CPU cycles aren't wasted on it until it becomes visible again.
It's the mechanism that powers Concurrent Mode's ability to "yield" to more important tasks.
05. Conditional vs. Hidden vs. Activity
| Method | State | Performance |
|---|---|---|
Conditional {show && |
Destroyed (Unmount) | Good (DOM removed) |
CSS display: none |
Preserved | Bad (Still re-renders invisibly) |
| <Activity /> | Preserved | Perfect (No re-renders while hidden) |