
React 性能优化
React 默认速度很快,但复杂应用会遭遇不必要的重渲染和过大的打包体积。本指南涵盖系统性的性能优化方法。
useMemo 和 useCallback
function ProductList({ products, onSelect }: Props) {
const [filter, setFilter] = useState('');
// 仅当依赖项变化时重新计算
const filtered = useMemo(() => {
return products
.filter(p => p.name.toLowerCase().includes(filter.toLowerCase()))
.sort((a, b) => a.name > b.name ? 1 : -1);
}, [products, filter]);
// 为记忆化子组件提供稳定引用
const handleSelect = useCallback((id: string) => {
onSelect(id);
}, [onSelect]);
return (
<div>
<input value={filter} onChange={e => setFilter(e.target.value)} />
{filtered.map(product => (
<ProductCard
key={product.id}
product={product}
onSelect={handleSelect}
/>
))}
</div>
);
}
const ProductCard = React.memo(({ product, onSelect }: Props) => {
return <div onClick={() => onSelect(product.id)}>{product.name}</div>;
});

大数据集的虚拟列表
import { FixedSizeList } from 'react-window';
const Row = ({ index, style, data }: any) => {
const item = data.items[index];
return (
<div style={style} onClick={() => data.onSelect(item.id)}>
{item.name} - ${item.price}
</div>
);
};
function VirtualProductList({ products, onSelect }: Props) {
const itemData = useMemo(
() => ({ items: products, onSelect }),
[products, onSelect]
);
return (
<FixedSizeList
height={600}
itemCount={products.length}
itemSize={60}
itemData={itemData}
>
{Row}
</FixedSizeList>
);
}
代码分割与懒加载
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Analytics = lazy(() => import('./pages/Analytics'));
function App() {
return (
<Suspense fallback={<PageSkeleton />}>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/analytics" element={<Analytics />} />
</Routes>
</Suspense>
);
}

useTransition 和 useDeferredValue
function SearchPage() {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setQuery(value); // 紧急:立即更新输入
startTransition(() => {
// 非紧急:如果用户再次输入可中断
setSearchResults(performSearch(value));
});
};
return (
<div>
<input value={query} onChange={handleChange} />
{isPending ? <Spinner /> : <Results />}
</div>
);
}
// useDeferredValue 用于昂贵渲染
function SearchResults({ query }: { query: string }) {
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
const results = useMemo(
() => performExpensiveSearch(deferredQuery),
[deferredQuery]
);
return (
<div style={{ opacity: isStale ? 0.7 : 1 }}>
{results.map(r => <ResultItem key={r.id} result={r} />)}
</div>
);
}
Context 优化
// 不好:单个 context 导致所有消费者重渲染
const AppContext = createContext({ user: null, cart: [], theme: 'light' });
// 好:按更新频率拆分 context
const UserContext = createContext<User | null>(null);
const CartContext = createContext<Cart>({ items: [], total: 0 });
const ThemeContext = createContext<'light' | 'dark'>('light');

性能检查清单
- 首先使用 React DevTools Profiler 进行分析
- 对 props 稳定的组件添加
React.memo - 对昂贵计算使用
useMemo - 对传递给记忆化子组件的处理函数使用
useCallback - 对超过 100 项的列表使用虚拟化
- 对路由和重型组件进行代码分割
- 对非紧急更新使用
useTransition - 避免在 JSX props 中使用内联对象/数组
总结
先分析,再优化。过度记忆化会增加复杂性而无益。React 的内置工具(useTransition、useDeferredValue)能优雅地处理并发渲染。