[ PROMPT_NODE_27994 ]
react-component-performance
[ SKILL_DOCUMENTATION ]
# React 组件性能
## 概述
识别渲染热点,隔离昂贵的更新,并在不改变 UI 行为的情况下应用针对性的优化。
## 何时使用
- 当用户要求分析或改进缓慢的 React 组件时。
- 当你需要减少 React UI 中的重复渲染、列表卡顿或昂贵的渲染工作时。
## 工作流
1. 重现或描述卡顿现象。
2. 识别触发重新渲染的原因(状态更新、属性变更、副作用)。
3. 将快速变化的状态与繁重的子树隔离开来。
4. 稳定属性和处理函数;在有价值的地方使用记忆化(memoization)。
5. 减少昂贵的操作(计算、DOM 大小、列表长度)。
6. **验证**:打开 React DevTools Profiler → 记录交互 → 检查 Flamegraph 中渲染时间超过 ~16 毫秒的组件 → 与优化前的基准记录进行对比。
## 检查清单
- 测量:使用 React DevTools Profiler 或记录渲染;捕获基准数据。
- 查找变动:识别在计时器、滚动、输入或动画上更新的状态。
- 分离:将频繁变动的状态移至子组件;保持繁重的列表为静态。
- 记忆化:仅在属性稳定时使用 `memo` 包装叶子行。
- 稳定属性:对处理函数和派生值使用 `useCallback`/`useMemo`。
- 避免在渲染中进行派生计算:预先计算,或在记忆化的辅助函数中计算。
- 控制列表大小:对长列表进行窗口化/虚拟化;避免渲染隐藏项。
- Keys:确保稳定的 key;当顺序可能改变时避免使用索引。
- 副作用:验证依赖数组;避免在每次渲染时重新运行的副作用。
- 样式/布局:注意昂贵的布局抖动或大型 Markdown/diff 渲染。
## 优化模式
### 隔离频繁变动的状态
将计时器或动画计数器移入子组件,这样父列表就不会在每次跳动时重新渲染。
tsx
// ❌ 之前 – 整个父组件(及列表)每秒重新渲染
function Dashboard({ items }: { items: Item[] }) {
const [tick, setTick] = useState(0);
useEffect(() => {
const id = setInterval(() => setTick(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return (
{/* 每秒重新渲染 */}
>
);
}
// ✅ 之后 – 只有 <Clock> 重新渲染;列表不受影响
function Clock() {
const [tick, setTick] = useState(0);
useEffect(() => {
const id = setInterval(() => setTick(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return {tick}s;
}
function Dashboard({ items }: { items: Item[] }) {
retur