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

自定义Hook中useEffect执行时机及Hook代码运行时机咨询

React自定义Hook的执行时机详解

一、自定义Hook中useEffect的执行时机

自定义Hook里的useEffect,执行时机和直接写在组件内部的useEffect完全一致:

  • 组件首次渲染完成(DOM更新后),Hook内的useEffect会依据依赖项规则执行回调;
  • 组件重新渲染时,只要useEffect的依赖项发生变更,其回调会在组件更新后的DOM操作完成后触发;
  • 本质上,自定义Hook只是组件逻辑的抽离复用,React会将Hook内部的所有Hook调用(包括useEffect)与使用它的组件绑定,等价于这些Hook直接写在组件内部。

举个直观的示例:

// 自定义Hook
function useMountLog() {
  useEffect(() => {
    console.log("组件挂载完成(来自自定义Hook)");
  }, []);
}

// 使用Hook的组件
function Profile() {
  useMountLog();
  return <div>用户资料页</div>;
}

这个例子中,useMountLog里的useEffect会在Profile组件首次渲染完成后执行,和直接把useEffect写在Profile组件里没有任何区别。

二、组件重新渲染时,自定义Hook内部代码的运行时机

当使用该Hook的组件(重新)渲染时,自定义Hook内部的非Hook回调代码(比如变量声明、普通函数调用、useState的初始化逻辑等)会和组件的渲染逻辑同步执行:

  • 组件启动渲染流程后,会按顺序执行内部代码;当遇到自定义Hook的调用时,会立即执行Hook内部的代码(useEffect、useLayoutEffect的回调除外,这类回调会延后到DOM更新阶段后执行);
  • 简单来说,自定义Hook的代码执行时机,就等同于把这段代码直接粘贴到调用它的组件对应位置,完全跟随组件的渲染流程走。

示例验证:

function useCounter() {
  console.log("自定义Hook内的普通代码执行");
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("Hook内的useEffect回调执行");
  }, [count]);

  return { count, setCount };
}

function CounterComponent() {
  console.log("组件渲染开始");
  const { count, setCount } = useCounter();
  console.log("组件渲染结束");

  return (
    <button onClick={() => setCount(c => c + 1)}>
      点击次数:{count}
    </button>
  );
}

首次渲染时的日志顺序为:

  1. 组件渲染开始
  2. 自定义Hook内的普通代码执行
  3. 组件渲染结束
  4. Hook内的useEffect回调执行

点击按钮触发组件重新渲染时,会重复前三条日志;若count值变更,第四条日志也会再次触发。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:22:46