自定义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> ); }
首次渲染时的日志顺序为:
- 组件渲染开始
- 自定义Hook内的普通代码执行
- 组件渲染结束
- Hook内的useEffect回调执行
点击按钮触发组件重新渲染时,会重复前三条日志;若count值变更,第四条日志也会再次触发。
内容的提问来源于stack exchange,提问作者Erfan Mirhoseini
相关产品推荐
相关产品推荐

