主题
useMemo
介绍
useMemo 是 React 中的一个 Hook,用于在函数组件中优化性能。它可以记住计算结果,避免在每次渲染时都进行重复计算。
快速入门
语法
ts
const memoizedValue = useMemo<T>(factory: () => T, dependencies: DependencyList)参数说明:
factory:用于返回需要缓存的值的函数,React 会在初始化和依赖变化时调用它。dependencies:依赖项数组,只有当数组中的某个值发生改变时,factory才会重新执行。
提示
useMemo 使用 Object.is 对依赖项逐个比较,和 useEffect、useCallback 的依赖比较规则一致。
示例
tsx
import { useMemo, useState } from 'react'
const allProducts = [
{ id: 1, title: 'React 入门教程', price: 99, category: 'course' },
{ id: 2, title: 'React 实战进阶', price: 199, category: 'course' },
{ id: 3, title: 'TypeScript 速查手册', price: 49, category: 'ebook' },
{ id: 4, title: 'CSS 灵感合集', price: 39, category: 'ebook' },
]
function ProductList() {
const [keyword, setKeyword] = useState('react')
const [category, setCategory] = useState('all')
const filteredProducts = useMemo(() => {
console.log('🔥 仅在依赖变化时重新计算')
return allProducts
.filter((item) => (category === 'all' ? true : item.category === category))
.filter((item) => item.title.toLowerCase().includes(keyword.toLowerCase()))
}, [keyword, category])
return (
<section style={{ display: 'grid', gap: 12 }}>
<input value={keyword} placeholder="搜索关键词" onChange={(event) => setKeyword(event.target.value)} />
<select value={category} onChange={(event) => setCategory(event.target.value)}>
<option value="all">全部</option>
<option value="course">课程</option>
<option value="ebook">电子书</option>
</select>
<ul style={{ margin: 0, paddingLeft: 18 }}>
{filteredProducts.map((product) => (
<li key={product.id}>
{product.title} - ¥{product.price}
</li>
))}
</ul>
</section>
)
}
export default ProductList滥用的后果
- 内存开销增加:每个 useMemo/useCallback 都需要内存来进行缓存。
- 初始渲染性能下降:React 需要额外的工作来管理这些缓存,对于一些简单计算,缓存开销可能比计算本身还要大。
- 代码复杂度增加
- 满屏的 useMemo/useCallback 会让代码变得冗长,降低可读性。
- 依赖数组管理增加心智负担。
- 容易出现依赖遗漏的 bug。
