React状态保留新方案:Activity组件实战指南
在开发中后台系统时,我们经常遇到这样的需求:用户在一个复杂的筛选面板中填写了很多条件,切换到其他页面后再回来,希望之前填写的内容还在。
面对这个问题,开发人员通常尝试几种方案:
现在好消息来了,react 19.2引入了Activity组件,专门解决这个问题。
传统方案的问题
方案1:条件渲染
function App() {
const [show, setShow] = useState(true);
return (
<>
{show && <FilterPanel />}
</>
);
}这种方式的问题:组件完全卸载,所有状态都会丢失。
方案2:CSS隐藏
function App() {
const [show, setShow] = useState(true);
return (
<div style={{ display: show ? 'block' : 'none' }}>
<FilterPanel />
</div>
);
}这种方式的问题:组件虽然看不见了,但仍在运行,useEffect还会执行,可能造成资源浪费。
方案3:手动状态管理
function TabContainer() {
const [cache, setCache] = useState({});
const handleTabChange = (tab) => {
// 保存当前状态
const currentData = getFormData();
setCache(prev => ({
...prev,
[currentTab]: currentData
}));
setCurrentTab(tab);
};
// 还要处理状态恢复、滚动位置等...
}这种方式代码量大,容易出错。
Activity组件的基本用法
React 19.2的Activity组件提供了优雅的解决方案:
import { Activity } from 'react';
function App() {
const [isVisible, setIsVisible] = useState(true);
return (
<Activity mode={isVisible ? 'visible' : 'hidden'}>
<FilterPanel />
</Activity>
);
}Activity组件的工作原理
当mode设置为'hidden'时:
当mode设置为'visible'时:
移除display: none样式
重新执行useEffect
组件恢复正常渲染
实际应用场景
场景1:Tab切换
function TabSystem() {
const [activeTab, setActiveTab] = useState('list');
return (
<div>
<nav>
<button onClick={() => setActiveTab('list')}>列表</button>
<button onClick={() => setActiveTab('form')}>表单</button>
</nav>
<Activity mode={activeTab === 'list' ? 'visible' : 'hidden'}>
<ProductList />
</Activity>
<Activity mode={activeTab === 'form' ? 'visible' : 'hidden'}>
<ProductForm />
</Activity>
</div>
);
}这样切换Tab时,每个Tab的状态都会保留。
场景2:侧边栏筛选
function DataPage() {
const [sidebarOpen, setSidebarOpen] = useState(true);
return (
<div className="page">
<button onClick={() => setSidebarOpen(!sidebarOpen)}>
{sidebarOpen ? '收起' : '展开'}筛选
</button>
<Activity mode={sidebarOpen ? 'visible' : 'hidden'}>
<SidebarFilters />
</Activity>
<MainContent />
</div>
);
}
function SidebarFilters() {
const [filters, setFilters] = useState({
category: '',
priceRange: [0, 1000],
keywords: ''
});
// 这些状态在侧边栏收起/展开时都会保留
return (
<div className="sidebar">
<input
value={filters.keywords}
onChange={(e) => setFilters({...filters, keywords: e.target.value})}
placeholder="搜索关键词"
/>
{/* 更多筛选条件 */}
</div>
);
}场景3:Modal对话框
function UserPage() {
const [modalOpen, setModalOpen] = useState(false);
return (
<div>
<button onClick={() => setModalOpen(true)}>
编辑用户信息
</button>
<Activity mode={modalOpen ? 'visible' : 'hidden'}>
<Modal onClose={() => setModalOpen(false)}>
<UserForm />
</Modal>
</Activity>
</div>
);
}
function UserForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
role: ''
});
// 即使用户关闭Modal,表单数据也会保留
// 下次打开时可以直接继续编辑
return (
<form>
<input
value={formData.name}
onChange={(e) => setFormData({...formData, name: e.target.value})}
/>
{/* 其他表单字段 */}
</form>
);
}资源管理
Activity组件的一个重要特性是能正确管理资源:
function DataMonitor({ deviceId }) {
const [data, setData] = useState(null);
useEffect(() => {
console.log('开始获取数据');
// 建立WebSocket连接
const ws = new WebSocket(`ws://api.example.com/devices/${deviceId}`);
ws.onmessage = (event) => {
setData(JSON.parse(event.data));
};
// 定时发送心跳
const heartbeat = setInterval(() => {
ws.send('ping');
}, 5000);
return () => {
console.log('清理资源');
clearInterval(heartbeat);
ws.close();
};
}, [deviceId]);
return <div>{/* 显示数据 */}</div>;
}当Activity的mode变为'hidden'时,useEffect的清理函数会自动执行,关闭WebSocket连接和定时器。
性能考虑
Activity组件虽然好用,但也要注意合理使用:
适合的场景:
Tab切换系统
侧边栏、抽屉组件
Modal对话框
需要保留状态的复杂表单
不适合的场景:
组件渲染特别慢(超过500ms)
内存受限的移动端应用
很少切换的页面
使用建议
对于频繁切换的组件,使用Activity可以提升用户体验
对于很少使用的功能,直接用条件渲染即可
注意内存使用,不要同时渲染太多hidden组件
与其他方案对比
| 方案 | 状态保留 | 资源清理 | 使用难度 |
|---|---|---|---|
| 条件渲染 | ❌ 不保留 | ✅ 会清理 | 简单 |
| CSS隐藏 | ✅ 保留 | ❌ 不清理 | 简单 |
| 手动管理 | ✅ 保留 | ⚠️ 需手动 | 复杂 |
| Activity | ✅ 保留 | ✅ 自动清理 | 简单 |
总结
React 19.2的Activity组件解决了前端开发中的一个常见痛点。它既保留了组件状态,又能正确管理资源,使用起来还很简单。
在实际项目中,你可以这样选择:
需要保留状态且频繁切换的组件 → 使用Activity
简单组件或很少切换的组件 → 使用条件渲染
特殊需求场景 → 考虑手动状态管理
Activity组件让React开发更加顺手,特别是在处理复杂交互场景时,能显著提升开发效率和用户体验。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!