Files
skillhub-088-vercel-react-b…/rules/rerender-split-combined-hooks.md
2026-07-13 21:36:17 +08:00

65 lines
1.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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),它会自动优化依赖追踪,部分上述情况可能已自动处理。