[ PROMPT_NODE_24804 ]
性能优化
[ SKILL_DOCUMENTATION ]
# 性能优化
优化 React 组件性能、防止不必要的重新渲染以及避免内存泄漏的模式。
---
## 记忆化 (Memoization) 模式
### 使用 useMemo 处理昂贵的计算
typescript
import { useMemo } from 'react';
export const DataDisplay: React.FC = ({
items,
searchTerm,
}) => {
// ❌ 避免 - 每次渲染都会运行
const filteredItems = items
.filter(item => item.name.includes(searchTerm))
.sort((a, b) => a.name.localeCompare(b.name));
// ✅ 正确 - 已记忆化,仅在依赖项改变时重新计算
const filteredItems = useMemo(() => {
return items
.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()))
.sort((a, b) => a.name.localeCompare(b.name));
}, [items, searchTerm]);
return ;
};
**何时使用 useMemo:**
- 过滤/排序大型数组
- 复杂计算
- 转换数据结构
- 昂贵的计算(循环、递归)
**何时不要使用 useMemo:**
- 简单的字符串拼接
- 基本算术运算
- 过早优化(先进行性能分析!)
---
## 使用 useCallback 处理事件处理器
### 问题所在
typescript
// ❌ 避免 - 每次渲染都会创建新函数
export const Parent: React.FC = () => {
const handleClick = (id: string) => {
console.log('Clicked:', id);
};
// 每次 Parent 渲染时 Child 都会重新渲染
// 因为 handleClick 每次都是一个新的函数引用
return ;
};
### 解决方案
typescript
import { useCallback } from 'react';
export const Parent: React.FC = () => {
// ✅ 正确 - 稳定的函数引用
const handleClick = useCallback((id: string) => {
console.log('Clicked:', id);
}, []); // 空依赖数组 = 函数永远不会改变
// 仅在 props 实际改变时 Child 才会重新渲染
return ;
};
**何时使用 useCallback:**
- 作为 props 传递给子组件的函数
- 作为 useEffect 依赖项使用的函数
- 传递给已记忆化组件的函数
- 列表中的事件处理器
**何时不要使用 useCallback:**
- 未传递给子组件的事件处理器
- 简单的内联处理器:`onClick={() => doSomething()}`
---
## 使用 React.memo 进行组件记忆化
### 基本用法
typescript
import React from 'react';
interface ExpensiveComponentProps {
data: ComplexData;