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

useEffect依赖更新时,其清理函数是否会同步在对应effect函数前执行?

useEffect同步清理函数的执行顺序保证

针对你的问题,在清理函数本身为同步函数的前提下,React官方明确保证:旧effect的清理函数一定会在对应新effect回调执行前被同步调用,该执行顺序是固定可预期的,不存在异步插队的可能。

固定执行流程

对于绑定了相同依赖项的同一个useEffect,其更新触发的完整流程是严格固定的:

  • 依赖项发生变化触发组件重渲染
  • 组件完成渲染、浏览器完成DOM绘制后,React开始处理effect队列
  • 第一步:同步执行上一次渲染生成的该effect对应的清理函数
  • 第二步:同步执行本次渲染生成的新effect回调
  • 首次渲染时不存在上一次的effect实例,因此不会执行清理逻辑,直接运行effect回调

常见误区说明

很多开发者会因为useEffect「不阻塞渲染」的特性误以为它的内部逻辑是异步打散的,实际上:

  • useEffect的调度时机是异步的:React会等浏览器绘制完成后再处理effect,避免阻塞UI更新
  • 但effect队列的执行过程是同步的:一旦React开始执行effect队列,会一口气完成所有旧effect清理→新effect执行的流程,中间不会插入任何其他宏任务、微任务,也就不会出现清理和新effect执行顺序错乱的情况

示例验证

你给出的示例代码的打印顺序是完全可复现的:

export default function App() {
  const [count, setCount] = useState(0);

  console.log("App: render");

  useEffect(() => {
    console.log("effect");
    return () => console.log("cleanup");
  }, [count]);

  return (
    <>
      <h2>useEffect</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </>
  );
}

每次点击Increment按钮触发count更新后,打印顺序必然为:

  1. App: render
  2. cleanup
  3. effect
    不存在任何例外情况。

卸载场景补充

组件卸载时,React同样会同步执行所有未清理的effect的清理函数,这个过程也是批量同步执行的,不会涉及异步逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:15:00