前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库React useEffect 依赖数组三种写法
ReReact副作用与同步

useEffect 不写依赖、空数组和具体依赖有什么区别?

依赖描述 Effect 读取哪些响应式输入,React 据此决定提交后是否需要重新同步。

前端进阶之旅 · 一题精讲更新于 2026.09.06
React#副作用与同步#Effect
先看核心答案
理解线索

三种写法对应三种重同步条件

  1. 省略参数每次该组件提交后都需要重跑
  2. 空数组没有列出的响应式依赖会触发重同步
  3. 具体依赖任何一项 Object.is 不同就重新同步

Hook 调用位置仍应固定;不要为了选择某一种模式在条件分支里调用 useEffect。

核心回答

先记住这个答案

省略第二个参数时,Effect 会在组件每次提交后重新运行;传空数组时,不会因为普通响应式依赖变化而重新同步,但仍有首次建立、卸载清理及开发检查;列出依赖时,首次建立之后,只要某项与上次通过 Object.is 比较不同,就需要先清理旧同步再建立新同步。依赖应由代码实际读取的值决定,不能只按希望执行几次来随意选择。

  • 比较发生在依赖项之间,不是比较依赖数组对象身份
  • 空数组不等于应用整个生命周期只执行一次
  • 依赖变化先清理旧一轮,再建立新一轮

省略参数为什么容易产生反馈循环

例如 Effect 每次提交后都调用 setter 保存一个新对象,更新又产生新提交,随后 Effect 再更新,就形成反馈循环。问题不是省略依赖在语法上非法,而是同步逻辑不断制造新的输入变化。先判断那个 state 是否必要,再决定依赖与更新方式,通常比直接补一个空数组更有效。

同时要准确使用“提交”一词:组件函数可能在开发检查或可中断渲染中执行,但未必都形成独立的已提交更新。观察日志时应把渲染计算和 Effect 执行分开,避免根据函数调用次数写出与实际生命周期不一致的判断。

空数组的约定不包含永久唯一执行

一个只使用固定浏览器事件名和本轮内部变量的订阅,可以没有动态依赖;它在挂载后建立,在卸载时清理。但切换路由后重新挂载会建立新的订阅,开发环境的 Strict Mode 检查也可能带来额外建立与清理周期。空数组不能充当全局去重或支付防重机制。

如果 Effect 内部读取 roomId,却传空数组,组件后续切到新房间时仍可能保持旧连接。此时不是 React 忽略了变化,而是依赖声明没有描述实际输入。不要把首次值恰好正确当作整个生命周期都正确,应通过修改输入与重新挂载两种操作分别验证。

列出依赖时关注每项值如何产生

依赖列表可以每次写成数组字面量,React 比较的是对应位置的每一项,而不是数组容器的引用。数字和字符串按 Object.is 判断值,对象与函数通常需要关注引用是否变化。如果配置对象每次重新创建,即便字段一样,也可能使同步不断重建。

依赖的数量与顺序应该固定并直接写出,便于工具分析。确实不想因某项输入重连时,应重新检查代码结构,例如把只需要在同步内部创建的对象移进去,或分开两个独立同步过程;不能用条件拼接依赖数组让 React 猜测当前是哪种同步约定。

回答前,多想一步

容易答错的地方

空数组会在服务端和客户端各执行一次
Effect 不在服务端渲染期间执行。客户端的挂载与开发检查需要单独理解,不能把服务器输出 HTML 也算成一次 Effect 建立。
依赖数组每次新建,所以 Effect 总会重跑
React 比较各个依赖项,不是这个数组对象本身。真正值得检查的是数组中的对象、函数或其它值是否变化,以及是否存在省略依赖参数的情况。
试着用自己的话回答

面试官还会怎么问?

依赖没变化时会先运行 cleanup 吗?

普通的同实例更新中,如果这一轮不需要重新同步,就不会仅因这次更新而执行该 Effect 的清理。卸载、开发检查等生命周期情形需要另外考虑。

依赖从 0 变成 -0 会被认为变化吗?

Object.is 能区分正零与负零,因此这两个依赖值不同;它也把 NaN 与 NaN 视为相同。多数业务不需要利用这种边界,但可以用它说明这里不是简单的等号比较。

想只记录首次打开页面,可以用空数组吗?

可以用挂载相关逻辑表达某个视图的展示,但仍要定义重新进入、开发检查和统计去重规则。可靠的事件口径不能只靠 Effect 看似运行一次来保证。

从一道题,走向一组知识

把知识连起来

副作用与同步

useEffect 为什么必须声明读到的响应式依赖,漏写会怎样?

依赖列表应由 Effect 实际读取的响应式值推导。

副作用与同步

useEffect 依赖对象或函数时,为什么可能每次渲染都重跑?

对象与函数依赖需要进一步理解引用身份为何会变化。

参考资料

  • React useEffect:依赖数组
  • Lifecycle of Reactive Effects

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 省略参数为什么容易产生反馈循环
  3. 空数组的约定不包含永久唯一执行
  4. 列出依赖时关注每项值如何产生
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑