项目文件夹

文件
2026-07-13 21:36:17 +08:00

65 行
1.8 KiB
Markdown

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
title: 拆分组合的 Hook 计算
impact: MEDIUM
impactDescription: 避免重新计算独立的步骤
tags: rerender, useMemo, useEffect, dependencies, optimization
---
## 拆分组合的 Hook 计算
当一个 Hook 包含多个具有不同依赖项的独立任务时,应将它们拆分为单独的 Hook。组合式的 Hook 在任意依赖项发生变化时会重新运行所有任务,即使某些任务并未使用已变化的值。
**错误(修改 `sortOrder` 会重新计算过滤):**
```tsx
const sortedProducts = useMemo(() => {
const filtered = products.filter((p) => p.category === category)
const sorted = filtered.toSorted((a, b) =>
sortOrder === "asc" ? a.price - b.price : b.price - a.price
)
return sorted
}, [products, category, sortOrder])
```
**正确(仅当 products 或 category 变化时才重新计算过滤):**
```tsx
const filteredProducts = useMemo(
() => products.filter((p) => p.category === category),
[products, category]
)
const sortedProducts = useMemo(
() =>
filteredProducts.toSorted((a, b) =>
sortOrder === "asc" ? a.price - b.price : b.price - a.price
),
[filteredProducts, sortOrder]
)
```
此模式同样适用于组合了不相关副作用的 `useEffect`
**错误(任一依赖变化时两个副作用都会执行):**
```tsx
useEffect(() => {
analytics.trackPageView(pathname)
document.title = `${pageTitle} | My App`
}, [pathname, pageTitle])
```
**正确(副作用独立执行):**
```tsx
useEffect(() => {
analytics.trackPageView(pathname)
}, [pathname])
useEffect(() => {
document.title = `${pageTitle} | My App`
}, [pageTitle])
```
**注意:** 如果你的项目启用了 [React Compiler](https://react.dev/learn/react-compiler),它会自动优化依赖追踪,部分上述情况可能已自动处理。