React Activity 保持 mode="visible" 能提升性能吗?
结论
仅用 <Activity mode="visible"> 包住 CompactView,即使它被 CSS 隐藏,React 也不会因此自动减少渲染或暂停 Effects。对于纯客户端渲染,这样做不会直接优化隐藏视图。
如果应用使用 SSR 和 hydration,始终为 visible 的 Activity 边界也可能通过参与 Selective Hydration,改善页面加载期间的交互响应。是否有实际收益,需要结合应用测量。React 官方文档
为什么 CSS 隐藏不会触发 Activity 的优化
示例中的 ExtendedView 和 CompactView 都在 React 组件树中,container query 只决定它们在浏览器中如何显示。
display: none 会让对应内容不参与布局和绘制,但不会卸载 React 组件,也不会自动停止其中的 Effects、订阅或定时器。React 不会根据 container query 的匹配结果自动修改 Activity 的 mode。
因此,即使 CompactView 在页面上不可见,下面的边界仍处于 visible 模式:
<Activity mode="visible">
<CompactView />
</Activity>
visible 是默认值,省略 mode 与显式设置它含义相同。Activity 属性说明
用户大多使用大屏幕,只能说明 CompactView 较少显示,不能据此判断这层包装会带来多少性能收益。
怎样减少隐藏视图的工作
如果希望隐藏视图保留状态,同时清理其 Effects,需要让 React 获得与 container query 一致的显示条件,再据此切换 mode。
下面假设 isCompact 已由外部根据实际容器尺寸计算,且 ExtendedView、CompactView 已在当前文件中定义或导入:
import { Activity } from 'react';
function ResponsiveViews({ isCompact }) {
return (
<>
<Activity mode={isCompact ? 'hidden' : 'visible'}>
<ExtendedView />
</Activity>
<Activity mode={isCompact ? 'visible' : 'hidden'}>
<CompactView />
</Activity>
</>
);
}
进入 hidden 模式后,Activity 会保留状态和 DOM,清理 Effects,并以较低优先级处理隐藏子树的渲染;恢复 visible 时会重新建立 Effects。hidden 不意味着完全停止渲染,也不会释放整棵子树占用的内存。Activity 行为说明
实现时需要注意:
- container query 依据容器尺寸,不能直接用屏幕或窗口宽度替代。可以通过 ResizeObserver 观察对应容器,再按相同规则计算
isCompact。 - CSS 与 JavaScript 要使用一致的断点和判断条件,否则可能出现 CSS 已显示、Activity 仍隐藏的情况。
- Effects 中创建的订阅、定时器等资源,需要在 cleanup 中释放。
如果切换视图时不需要保留各自的内部状态,可以直接条件渲染:
return isCompact ? <CompactView /> : <ExtendedView />;
这样不会挂载未选中的视图,但切换时会卸载旧视图,其内部状态也会丢失。
如何判断是否值得改动
如果想解决 SSR 页面加载期间交互迟缓的问题,可以测量 visible Activity 边界对 hydration 的影响;如果隐藏视图仍在运行订阅或发生昂贵更新,可以考虑动态切换 hidden 或条件渲染。
使用 React DevTools Profiler 和浏览器 Performance 面板,对比初次加载、容器尺寸切换以及常见数据更新的情况。原问题没有提供 SSR 配置、组件开销或测量结果,因此无法承诺这次包装能带来性能提升。
备注:内容仅供参考。
