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

React中未设依赖的useEffect是否每次重渲染都执行?为何最后一次未触发ef1?

问题分析:为什么第三次重渲染未执行ef1?

你的代码核心是探究不同依赖项的useEffect执行机制,实际输出与预期的差异,根源在于React的异步状态更新、批量更新机制以及useEffect的执行规则,下面一步步拆解:

正确的执行流程(React 18)

1. 第一次渲染(初始渲染)

  • 组件函数执行,输出 I'm in...,此时 st1="",st2=""
  • 所有useEffect的setup函数依次执行(首次渲染时,无论依赖项如何都会执行):
    • ef1(无依赖):输出 ef1
    • ef2(空依赖数组):输出 ef2,调用 setSt1("st1") → 将更新加入队列
    • ef3(依赖st1):输出 ef3,调用 setSt2("st2") → 将更新加入队列
    • ef4(依赖st1、st2):输出 ef4
  • React合并队列中的setSt1和setSt2更新,触发第二次渲染(批量更新优化,避免多次重渲染)

2. 第二次渲染

  • 组件函数执行,输出 I'm in...,此时 st1="st1",st2="st2"
  • 进入effect执行阶段:
    • ef1(无依赖,每次渲染后必执行):输出 ef1
    • ef2(空依赖数组,仅首次渲染执行):跳过
    • ef3(依赖st1:旧值"" → 新值"st1",依赖变化):输出 ef3,调用 setSt2("st2") → 新值与当前st2("st2")完全相同,React不会触发重渲染
    • ef4(依赖st1、st2:st1变化):输出 ef4

此时不会出现第三次渲染,但你的实际输出有第三次I'm in...,说明你可能使用的是React 17或更早版本——这类版本中,effect内的setState不会被批量处理,且即使新值与旧值相同,也可能触发重渲染(开发模式下的调试行为)。

为什么第三次重渲染后没执行ef1?

如果确实出现了第三次渲染,那唯一的解释是:这次渲染是React开发模式下的严格模式重复渲染。

在React 18的严格模式中,开发环境下会对组件渲染进行一次"模拟卸载-重新挂载"的操作,以检测副作用问题。这次模拟的重新渲染:

  • 会执行组件函数(输出I'm in...)
  • 但会跳过effect的执行(因为是模拟操作,避免重复触发副作用)

这就是你看到第三次I'm in...后没有任何ef1输出的原因。

验证方法

你可以关闭严格模式(去掉index.js中的<StrictMode>标签),重新运行代码:

  • 此时只会出现两次I'm in...
  • 第二次渲染的effect阶段会正常执行ef1、ef3、ef4,不会有第三次渲染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:24:54