如何在 React 中正确处理 useEffect 的依赖数组以避免闭包陷阱?

如何在 React 中正确处理 useEffect 的依赖数组以避免闭包陷阱?

回答:
在 React 的 useEffect 中,应确保依赖数组包含所有在 effect 中引用的外部变量(包括 props、state 和函数)。若遗漏依赖项,会导致闭包捕获旧值,产生“过时闭包”问题。为避免此问题:

  1. 完整列出依赖:将 effect 中使用的所有响应式值(state、props、由它们派生的值、或在组件内定义的函数)加入依赖数组。
  2. 使用 ESLint 插件:启用 eslint-plugin-react-hooksexhaustive-deps 规则,自动检测缺失依赖。
  3. 稳定函数引用:若依赖函数,使用 useCallback 包裹该函数,避免每次渲染都生成新引用,导致无限循环。
  4. 必要时使用 ref:若确实需要访问最新值而不触发 effect 重运行,可将值存入 ref,并在 effect 中读取 ref.current。

示例:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      // 错误:直接使用 count 会导致始终为初始值 0
      // setCount(count + 1);
      
      // 正确:使用函数式更新
      setCount(c => c + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []); // 依赖数组为空,但需确保不依赖外部变量

  return <div>{count}</div>;
}

解析:
闭包陷阱源于 effect 在创建时捕获了当时作用域中的变量值。若这些变量后续更新但未被列为依赖,effect 内部仍使用旧值。通过严格管理依赖数组并结合函数式状态更新或 ref,可确保逻辑始终基于最新状态,同时避免不必要的重复执行或无限循环。

发表评论 (审核通过后显示评论):

昵称:
邮箱:
内容: