news 2026/10/5 10:21:29

在 next-shadcn-dashboard-starter 中用好 React `<Activity>` 组件:以 hidden 模式保留昂贵组件的状态与 DOM

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 next-shadcn-dashboard-starter 中用好 React `<Activity>` 组件:以 hidden 模式保留昂贵组件的状态与 DOM
  • 前端
  • 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.

项目地址:https://gitcode.com/gh_mirrors/ne/next-shadcn-dashboard-starter
点击查看免费下载

本篇技术指南聚焦 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 定义了这条规则的元信息:

字段值含义
titleUse Activity Component for Show/Hide规则标题:用 Activity 组件处理显隐
impactMEDIUM影响等级:中等性能提升
impactDescriptionpreserves state/DOM核心收益:保留状态与 DOM
tagsrendering, 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 语义可以推断出它在性能上的双重作用:

  1. 状态与 DOM 存续:子树不卸载,useState、useRef、DOM 节点、滚动位置、展开/折叠状态在隐藏期间原样保留,重新打开时"所见即所得";
  2. 渲染工作可推迟:hidden 子树被视为低优先级渲染单元,React 可以在主界面繁忙时将它的更新延后处理,避免阻塞用户当前看到的交互;
  3. 避免重挂载风暴:对于树深、依赖多、副作用重的组件,反复卸载/挂载的成本远高于"隐藏—恢复",这也是规则强调"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 用 CSScontent-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:长列表用 CSScontent-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.

项目地址:https://gitcode.com/gh_mirrors/ne/next-shadcn-dashboard-starter
点击查看免费下载

相关推荐

上一篇:Metabase `Offset` 表达式完全指南:跨行取值、LAG/LEAD 窗口函数与同比(YoY)分析实战
下一篇:Vant 移动端 Layout 布局组件完全指南:Row / Col 24 栅格系统的配置、源码原理与实战

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 10:17:40

3 条命令搞定抖音无水印批量下载:douyin-downloader 实操手册

3 条命令搞定抖音无水印批量下载&#xff1a;douyin-downloader 实操手册 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallbac…

作者头像 李华
网站建设 2026/10/5 10:13:49

类变量和全局变量的生命周期有什么区别?

Python&#xff1a;类变量 vs 全局变量 — 生命周期区别核心一句话&#xff1a; 全局变量依附模块&#xff1b;类变量依附类对象。谁的宿主活着&#xff0c;变量就活着&#xff1b;宿主被 GC 回收&#xff0c;变量跟着销毁。一、全局变量全局变量定义在模块顶层&#xff0c;保存…

作者头像 李华
网站建设 2026/10/5 10:09:01

(进阶数据结构)图论

目录 图的基本概念 图的存储和遍历 邻接矩阵 邻接表 图的遍历 构造最小生成树 Kruskal算法 Prim算法 最短路径问题 单源最短路径 Dijkstra算法 Bellman-Ford算法 多源最短路径 Floyd-Warshall算法 参考代码 图的基本概念 图是由顶点集合及顶点间的关系&#xff…

作者头像 李华
网站建设 2026/10/5 10:02:26

STM32CubeMX图形化配置指南:从引脚分配到代码生成,避开常见坑

说实话&#xff0c;我最早对STM32CubeMX是很不以为然的。上学那会儿习惯了自己写寄存器、自己搭工程&#xff0c;总觉得图形化配置工具是给偷懒的人准备的。后来工作里做产品原型&#xff0c;一周内要复用到三块不同型号的板子&#xff0c;光是把时钟树撸明白、把外设初始化调试…

作者头像 李华