- 前端
- UI组件
【免费下载链接】next-shadcn-dashboard-starter
Free, open source, AI-friendly admin dashboard template built with Next.js 16, shadcn/ui, Tailwind CSS, and TypeScript. Production-ready tables, forms, auth, and billing. MIT licensed.
本篇技术指南聚焦 next-shadcn-dashboard-starter 仓库内置的 Vercel React 最佳实践规则rendering-activity.md,讲解如何用 React 19 的<Activity>组件替代"卸载—重挂载"的显隐方式,为高频切换可见性的昂贵组件保留状态与 DOM。读完本文,你将掌握<Activity>的visible/hidden两种模式的正确用法、其与条件渲染及 CSS 隐藏的本质差异,以及如何在当前项目的弹窗、侧边栏、通知中心等场景落地这一优化。
规则出处:Vercel React Best Practices 技能库
这条规则来自仓库中.agents/skills/vercel-react-best-practices/技能目录,它是 Vercel 维护的一套面向 React / Next.js 的性能优化指南。按 SKILL.md 的说明,该技能包含64 条规则、8 大分类,并按影响程度(CRITICAL → LOW)排序,用于指导代码编写、评审与重构。
规则文件本体为 rendering-activity.md,其 Frontmatter 定义了这条规则的元信息:
| 字段 | 值 | 含义 |
|---|---|---|
title | Use Activity Component for Show/Hide | 规则标题:用 Activity 组件处理显隐 |
impact | MEDIUM | 影响等级:中等性能提升 |
impactDescription | preserves state/DOM | 核心收益:保留状态与 DOM |
tags | rendering, activity, visibility, state-preservation | 检索标签 |
在 SKILL.md 的优先级表中,它归属于第 6 类 "Rendering Performance(渲染性能)",同类别下还有rendering-content-visibility(长列表用content-visibility)、rendering-conditional-render(显式条件渲染)、rendering-hoist-jsx(静态 JSX 提升)等规则,共同目标都是"减少浏览器在渲染阶段的工作量"(见 _sections.md)。
规则原文:用<Activity>保留显隐组件的状态与 DOM
规则正文给出了明确的使用范式:
Use React's
<Activity>to preserve state/DOM for expensive components that frequently toggle visibility.
用法示例(原文完整继承):
import { Activity } from 'react'; function Dropdown({ isOpen }: Props) { return ( <Activity mode={isOpen ? 'visible' : 'hidden'}> <ExpensiveMenu /> </Activity> ); }规则结论一句话点明收益:Avoids expensive re-renders and state loss(避免昂贵重渲染与状态丢失)。
<Activity>是 React 19 提供的一个显隐原语,通过mode属性控制子树的可视性:
mode="visible":子树正常渲染并参与布局与交互;mode="hidden":子树保持挂载,但从屏幕渲染中移除,且不会触发卸载。
与{isOpen && <ExpensiveMenu />}这类条件渲染的本质区别在于:条件渲染在关闭时会卸载子树,再次打开时需要重新执行组件初始化、重新计算所有派生状态、重新挂载副作用,并丢失打开期间积累的 DOM 状态(如滚动位置、输入焦点、受控表单值);而<Activity mode="hidden">让组件始终挂在组件树中,React 可以把它当作低优先级的"屏幕外"工作来推迟其渲染与副作用调度,从而在频繁开合时避免重复的昂贵渲染。这也是 Frontmatter 中impactDescription: preserves state/DOM的技术依据。
从 API 语义推断:hidden 模式如何同时带来"低开销"与"保状态"
从规则示例与<Activity>的 API 语义可以推断出它在性能上的双重作用:
- 状态与 DOM 存续:子树不卸载,
useState、useRef、DOM 节点、滚动位置、展开/折叠状态在隐藏期间原样保留,重新打开时"所见即所得"; - 渲染工作可推迟:hidden 子树被视为低优先级渲染单元,React 可以在主界面繁忙时将它的更新延后处理,避免阻塞用户当前看到的交互;
- 避免重挂载风暴:对于树深、依赖多、副作用重的组件,反复卸载/挂载的成本远高于"隐藏—恢复",这也是规则强调"expensive components that frequently toggle visibility"的原因——优化目标只针对"昂贵"且"高频切换"的组件。
需要说明:<Activity>的隐藏不等于 CSSdisplay: none与浏览器渲染层的直接对应,其核心价值在 React 调度层面;而"组件继续挂载"也意味着它占用的内存不会释放,因此它适合"频繁开关"而非"极少数出现"的场景(决策标准见下文)。
在 next-shadcn-dashboard-starter 中的落地场景
当前项目是基于 Next.js 16 + React 19.2 + shadcn/ui + Tailwind CSS 4 的管理后台模板(见 package.json),react: 19.2.4与react-dom: 19.2.4为<Activity>提供了运行时基础。仓库中存在大量"高频显隐 + 内部状态丰富"的交互组件,正是这条规则的典型应用对象:
- 弹窗与抽屉:
src/components/ui/dialog.tsx、src/components/ui/sheet.tsx、src/components/ui/modal.tsx(内部通过Dialog open={isOpen}受控显隐); - 侧边栏与移动端导航:
src/components/ui/sidebar.tsx与src/components/layout/app-sidebar.tsx中存在移动端抽屉式的开合状态; - 信息侧栏:
src/components/ui/infobar.tsx通过openMobile/setOpenMobile管理侧栏开合; - 下拉与命令面板:
dropdown-menu.tsx、.agents之外src/components/kbar/index.tsx命令面板等。
以规则中的 Dropdown 为例,若把ExpensiveMenu换成项目的通知中心或命令面板这类"打开即执行大量渲染"的组件,重构范式是统一的:
import { Activity } from 'react'; import { NotificationCenter } from '@/features/notifications/components/notification-center'; function HeaderNotifications({ isOpen }: { isOpen: boolean }) { return ( <Activity mode={isOpen ? 'visible' : 'hidden'}> <NotificationCenter /> </Activity> ); }这样通知中心内部的未读数状态、筛选条件、滚动位置都不会因面板关闭而丢失,再次打开时也不必重建整棵组件树。同理可套用到 Kanban 看板的新任务弹窗(src/features/kanban/components/new-task-dialog.tsx)——表单填写到一半被临时收起后,重新打开依然保留草稿,这正是state-preservation的直接收益。
使用决策指南:什么时候该用,什么时候不该用
结合规则语义与项目实际,给出可执行的取舍标准:
推荐使用<Activity mode="hidden">的场景:
- 组件树昂贵(图表、长列表、复杂表单、数据表格)且频繁开关;
- 打开状态涉及滚动位置、输入内容、筛选条件等必须保留的 DOM/状态;
- 显隐切换是同一用户会话内的瞬时交互(如侧边栏折叠、详情抽屉开合)。
不建议使用的场景:
- 组件极少展示、开关频率极低——让子树常驻内存反而浪费;
- 子树的 DOM 规模极大且长期隐藏——内存占用不可忽略,可参考同技能库的 rendering-content-visibility.md 用 CSS
content-visibility: auto延迟离屏项的布局与绘制; - 需要搜索引擎可见的内容——hidden 子树脱离正常渲染语义,首屏可访问性应交给服务端渲染/条件渲染;
- 条件本身只是
0/NaN等假值判断——那属于 rendering-conditional-render.md 解决的显式三元表达式问题,与<Activity>无关。
适用前提与运行验证
- 版本前提:
<Activity>依赖 React 19 及以上版本。当前仓库 package.json 锁定react/react-dom为19.2.4,可直接从'react'模块导入,TypeScript 类型随包提供; - 导入方式:与规则原文一致,使用具名导入
import { Activity } from 'react',无需额外安装依赖; - 运行验证:仓库同时提供
bun.lock/bunfig.toml与 package.json 脚本,可执行bun install或npm install后运行bun dev/npm run dev启动开发环境,在浏览器 DevTools 的 React 组件树中即可观察 hidden 状态下子树保持挂载、且状态未重置。
同分类相关规则速查
rendering-activity属于技能库第 6 类 "Rendering Performance",与该主题互补的相邻规则还有:
- rendering-conditional-render.md:用三元表达式替代
&&,避免渲染出0/NaN; - rendering-hoist-jsx.md:把静态 JSX 提到组件外复用,避免每次渲染重建;
- rendering-content-visibility.md:长列表用 CSS
content-visibility: auto延迟离屏渲染。
它们与<Activity>一起构成"渲染性能"维度的完整工具箱:条件渲染负责"正确显隐",<Activity>负责"高频显隐保状态",content-visibility负责"长列表降开销"。在 next-shadcn-dashboard-starter 这类交互密集的后台模板中,将这几条规则配合使用,可以显著减少重复渲染与状态丢失带来的卡顿感。
- 前端
- UI组件
【免费下载链接】next-shadcn-dashboard-starter
Free, open source, AI-friendly admin dashboard template built with Next.js 16, shadcn/ui, Tailwind CSS, and TypeScript. Production-ready tables, forms, auth, and billing. MIT licensed.
相关推荐
用 React `<Activity>` 组件管理显隐切换:在 Langfuse 前端保留昂贵组件的状态与 DOM
用 React <Activity 组件管理显隐切换:在 Langfuse 前端保留昂贵组件的状态与 DOM <Activity 是 React 19.2 起提
人工智能LLMOps可观测性AI 评测LLM 网关后端前端OpenMontage 中的 React `<Activity>` 组件实践:用隐藏而非卸载保住昂贵组件的状态与 DOM
OpenMontage 中的 React <Activity 组件实践:用隐藏而非卸载保住昂贵组件的状态与 DOM 导读 在 React / Next.js 应
人工智能AI Agent音视频媒体生成工作流自动化在 Polar 前端中用好 React Activity 组件:为高频显隐场景保留状态与 DOM
在 Polar 前端中用好 React Activity 组件:为高频显隐场景保留状态与 DOM 导读 本篇文章围绕 .agents/skills/vercel
后端前端金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考