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

1.8 KiB
Raw Permalink Blame History

title, impact, impactDescription, tags
title impact impactDescription tags
拆分组合的 Hook 计算 MEDIUM 避免重新计算独立的步骤 rerender, useMemo, useEffect, dependencies, optimization

拆分组合的 Hook 计算

当一个 Hook 包含多个具有不同依赖项的独立任务时,应将它们拆分为单独的 Hook。组合式的 Hook 在任意依赖项发生变化时会重新运行所有任务,即使某些任务并未使用已变化的值。

错误(修改 sortOrder 会重新计算过滤):

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 变化时才重新计算过滤):

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

错误(任一依赖变化时两个副作用都会执行):

useEffect(() => {
  analytics.trackPageView(pathname)
  document.title = `${pageTitle} | My App`
}, [pathname, pageTitle])

正确(副作用独立执行):

useEffect(() => {
  analytics.trackPageView(pathname)
}, [pathname])

useEffect(() => {
  document.title = `${pageTitle} | My App`
}, [pageTitle])

注意: 如果你的项目启用了 React Compiler,它会自动优化依赖追踪,部分上述情况可能已自动处理。