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

自定义Hook中,为何需将useEffect依赖项中的状态setter函数用括号包裹?

React自定义Hook中useEffect未触发的问题解析

先看你的代码场景:

import { useState, useEffect, useContext } from "react";
import { GlobalContext } from "context/GlobalState";

const useMyCustomHook = () => {
  const { myGlobalContext } = useContext(GlobalContext);

  const [myState, setMyState] = useState<MyStateType | null>(null);

  useEffect(() => {
    console.log("This code is never triggered.");
  }, [myGlobalContext, setMyState]);

  return myState;
};

你遇到的情况是:当依赖数组包含setMyState时,useEffect的回调从未执行,但移除它或者把它包裹成[setMyState]后,功能恢复正常。下面是问题的核心原因和正确做法:

核心原因:React对setter函数的稳定性保证

React的useState返回的setter函数(比如这里的setMyState)是全局稳定的——组件每次重新渲染时,同一个useState调用返回的setter引用完全一致,不会发生变化。

原代码的问题本质是对依赖数组的误解:

  1. 原依赖数组[myGlobalContext, setMyState]中,setMyState永远不会变化,所以只有当myGlobalContext变化时,useEffect才会触发。如果原场景中myGlobalContext从未发生过变化,回调自然不会执行;
  2. 把setMyState包裹成[setMyState]时,这个数组是每次渲染都会生成的新引用,会导致组件每次渲染都触发useEffect回调——这只是一种强制触发的hack,绝非正确写法;
  3. 移除setMyState后,依赖数组只剩myGlobalContext,此时只要myGlobalContext变化,useEffect就会正常触发,这才是符合预期的正确逻辑。

正确做法

永远不要把useState的setter函数放进useEffect的依赖数组里,React官方明确保证:setter函数的引用在组件生命周期内是不变的,完全不需要作为依赖项添加。

你的正确代码应该是:

//...
  useEffect(() => {
    console.log("This code will trigger when myGlobalContext changes.");
  }, [myGlobalContext]);
//..

至于你提到的“将依赖项用嵌套括号包裹”,这根本不是React的官方要求,只是一种会导致依赖数组每次渲染都变化的hack手段,完全不推荐使用——它会让useEffect在每次组件渲染时都执行,通常不是业务需要的逻辑,还可能引发性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 09:43:26