You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么React Hooks的useEffect、useCallback依赖项要加入setCount

为什么 useState 返回的 setter 函数需要放入 Hooks 依赖数组

核心逻辑说明

  • 首先要明确 React Hook 的基础依赖规则:所有在 useEffect、useCallback、useMemo 回调内部用到的外部变量、函数,都必须列入依赖数组,这是 react-hooks/exhaustive-deps ESLint 校验插件的强制要求,漏加会抛出警告。
  • 其次要知道 useState 返回的 setter 函数的特性:React 官方明确保证,同一个 useState 调用返回的 setter 函数,在组件整个挂载生命周期内引用永远不会发生变化,所以把它加入依赖数组,永远不会触发 useEffect 重复执行、也不会导致 useCallback/useMemo 返回新的引用。

为什么不能省略这个稳定的依赖

很多人会觉得既然 setter 引用不会变,加不加都不影响运行,为什么还要强制加?主要有两个原因:

  1. 统一规则降低维护成本:ESLint 校验规则无法区分你用的函数是 React 原生的稳定 setter 还是自己封装的不稳定函数,统一要求所有用到的变量都进依赖数组,可以避免后续代码迭代时出现闭包旧值的隐性bug。
  2. 避免逻辑变更带来的问题:如果后续你把原生的 setter 替换成自定义封装的修改逻辑,只要你遵守了依赖规则,不需要改动依赖数组就能正常运行,反之如果之前省略了依赖,就会直接出现闭包问题。

代码示例说明

正常示例

import { useState, useEffect, useCallback } from 'react';

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

  // 示例1:useEffect 中使用了 setCount
  useEffect(() => {
    // 模拟每3秒自动计数+1
    const timer = setInterval(() => {
      setCount(prev => prev + 1);
    }, 3000);
    return () => clearInterval(timer);
  }, [setCount]); 
  // 这里加入setCount不会导致effect重复执行,因为setCount引用永远不变,effect只会在组件挂载时运行一次

  // 示例2:useCallback 中使用了 setCount
  const increment = useCallback(() => {
    setCount(prev => prev + 1);
  }, [setCount]);
  // 这里加入setCount可以保证increment引用永远稳定,避免传递给子组件时导致不必要的重渲染

  return (
    <div>
      <p>当前计数:{count}</p>
      <button onClick={increment}>手动+1</button>
    </div>
  );
}

反例说明(省略依赖的风险)

如果你使用的是自定义封装的修改函数,不是原生的useState setter,省略依赖就会直接出现问题:

import { useState, useCallback } from 'react';

// 自定义封装的计数Hook,返回的修改函数引用不稳定
function useCustomCount() {
  const [count, setCount] = useState(0);
  // 每次组件重渲染都会生成新的customSetCount函数
  const customSetCount = (val) => {
    console.log('触发计数修改');
    setCount(val);
  }
  return [count, customSetCount];
}

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

  const increment = useCallback(() => {
    setCount(prev => prev + 1);
  }, []); // 省略了setCount依赖,调用的永远是第一次渲染的旧customSetCount

  // 如果后续customSetCount逻辑依赖了其他变量,就会出现闭包旧值的bug
  return <button onClick={increment}>手动+1</button>;
}

内容的提问来源于stack exchange,提问作者Azizjon Nuryagdyyev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:09:02