React 性能优化实战:让你的应用飞起来
深入理解 React 渲染机制,学习 memo、useMemo、useCallback 的正确使用方式。
React 渲染机制
理解 React 的渲染机制是性能优化的基础。当组件的 state 或 props 发生变化时,React 会重新渲染该组件及其所有子组件。
使用 React.memo
React.memo 可以避免不必要的重新渲染:
// ❌ 每次父组件渲染都会重新渲染
function ExpensiveComponent({ data }) {
return <div>{/* 复杂的渲染逻辑 */}</div>
}
// ✅ 只有 props 变化时才重新渲染
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
return <div>{/* 复杂的渲染逻辑 */}</div>
})
使用 useMemo
useMemo 用于缓存计算结果:
function ProductList({ products, filter }) {
// ❌ 每次渲染都会重新计算
const filteredProducts = products.filter(p => p.category === filter)
// ✅ 只有 products 或 filter 变化时才重新计算
const filteredProducts = useMemo(
() => products.filter(p => p.category === filter),
[products, filter]
)
return (
<ul>
{filteredProducts.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
)
}
使用 useCallback
useCallback 用于缓存函数引用:
function Parent() {
const [count, setCount] = useState(0)
// ❌ 每次渲染都会创建新函数
const handleClick = () => {
console.log('clicked')
}
// ✅ 函数引用保持稳定
const handleClick = useCallback(() => {
console.log('clicked')
}, [])
return <Child onClick={handleClick} />
}
虚拟列表
对于长列表,使用虚拟列表只渲染可见区域:
import { useVirtualizer } from '@tanstack/react-virtual'
function VirtualList({ items }) {
const parentRef = useRef(null)
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
})
return (
<div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
<div style={{ height: virtualizer.getTotalSize() }}>
{virtualizer.getVirtualItems().map(virtualItem => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: virtualItem.start,
height: virtualItem.size,
}}
>
{items[virtualItem.index]}
</div>
))}
</div>
</div>
)
}
代码分割
使用 React.lazy 和 Suspense 进行代码分割:
const HeavyComponent = React.lazy(() => import('./HeavyComponent'))
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
)
}
总结
React 性能优化的关键是减少不必要的渲染和计算。合理使用 memo、useMemo、useCallback,结合虚拟列表和代码分割,可以显著提升应用性能。
Bruce
全栈开发工程师,热爱技术分享
感谢阅读!如果这篇文章对你有帮助,欢迎分享给更多的朋友。