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

JavaScript清理函数工作原理?React useEffect返回函数执行逻辑解惑

关于React useEffect清理函数执行时机的疑惑

我目前正在学习React,过程中接触到了防抖(debouncing)概念,该概念与useEffect Hook相关。我已开始理解防抖的含义,但对清理函数的工作机制存在疑惑,具体来说,我无法理解useEffect中的返回函数为何会在钩子内所有代码执行前运行?

代码示例:

useEffect(() => {
  console.log('Before cleanup');

  return () => {
    console.log('Cleanup');
  };

}, []);

首先得纠正你的误解:你贴的这段代码里,清理函数根本不会在钩子内代码执行前运行。

咱们拆解下这段代码的执行流程:

  • 组件第一次挂载时,React会执行useEffect里的主逻辑:先打印Before cleanup,然后把返回的清理函数(那个打印Cleanup的箭头函数)保存起来,此时这个清理函数并没有被调用。
  • 因为你的useEffect依赖是[](空数组),这个钩子只会在组件挂载时执行一次,所以清理函数只有在组件卸载的时候(比如页面跳转、组件被从DOM中移除)才会被React调用,打印Cleanup。

那你为什么会有“清理函数在钩子代码前运行”的错觉?大概率是混淆了「依赖项变化」的场景。比如当useEffect有依赖变量时,每次依赖更新,React会先调用上一次钩子返回的清理函数,再执行新的钩子主逻辑。举个例子:

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

useEffect(() => {
  console.log(`当前count值:${count}`);

  return () => {
    console.log(`清理上一次的count:${count}`);
  };
}, [count]); // 依赖count变量

这个例子的执行顺序是:

  1. 组件挂载:执行主逻辑,打印当前count值:0,保存清理函数(会打印清理上一次的count:0)
  2. 点击按钮把count改成1:React先调用上一次的清理函数,打印清理上一次的count:0,然后执行新的主逻辑,打印当前count值:1,保存新的清理函数
  3. 组件卸载:调用最后一次的清理函数,打印清理上一次的count:1

简单来说,清理函数的触发时机只有两个:

  • 组件即将卸载时
  • 当前useEffect即将重新执行(依赖变化)前

它的核心作用就是清理副作用残留,比如防抖场景里的定时器——每次触发新的防抖逻辑前,先清理上一次未执行的定时器,避免多个定时器堆积,这也是防抖和useEffect清理函数结合的关键逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:02:51