前端进阶之旅前端进阶之旅
  • 基础篇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 exhaustive-deps 漏依赖
ReReact副作用与同步

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

依赖告诉 React 哪些输入变化后必须重新同步;漏写会让外部系统继续对应旧的渲染快照。

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

从代码读取关系检查重同步条件

  1. 响应式输入props、state 和组件体内产生的相关值
  2. 同步关系输入改变后外部连接或订阅是否应随之改变
  3. 工具检查静态依赖检查指出可能被遗漏的变化来源

ref.current 的原地变化不会触发渲染,不能靠把它写进依赖数组来建立可靠订阅。

核心回答

先记住这个答案

Effect 读取的 props、state,以及组件内根据它们形成的变量和函数,都可能随渲染变化。依赖列表应覆盖这些响应式输入,使 React 在值改变后清理旧同步并建立新同步。遗漏依赖常表现为连接还指向旧对象、定时回调读取旧值或请求使用上一个参数。exhaustive-deps 检查帮助发现这种数据关系缺口,处理警告时应调整真实代码结构,而不是默认关闭规则。

  • 依赖由 Effect 实际读取的输入推导
  • 闭包保存某轮输入,不能自动变成最新快照
  • 不想重新同步时要重构职责,不能隐瞒依赖

漏掉文档 ID 为什么会显示旧订阅结果

假设 Effect 根据 documentId 订阅实时审阅记录,但只声明服务地址作为依赖。文档切换后,组件可以已经显示新标题,旧 Effect 却没有因为 ID 变化而重新建立,于是侧栏仍收到旧文档记录。这个错位来自界面输入和外部同步使用了不同快照。

给依赖补上 documentId,让切换明确触发旧订阅清理和新订阅建立,才恢复了数据关系。若新依赖导致高频重连,还要检查它为何频繁变化、同步范围是否合理;不能因为修正后暴露了额外工作,就再把必要依赖删除。

把独立同步和事件读取分开

一个 Effect 同时管理文档连接与页面背景设置,背景颜色变化就可能连带重建连接。更清楚的结构是把两个外部关系拆开,各自依赖真正需要的输入。拆分不是为了把数组写短,而是让每个过程的重新同步条件与它负责的资源一致。

另一些回调只在连接事件发生时需要读取最新通知偏好,却不要求偏好一变就重新连接。支持 useEffectEvent 的 React 版本可以用它表达这种非响应式的 Effect 事件逻辑,但不能把它作为逃避所有依赖的通道。连接目标等决定同步关系的值仍然必须保留在依赖中,并遵守对应 Hook 的调用限制。

减少依赖应通过证明代码不再读取它

如果定时器只是基于旧计数加一,可以让 setter 接收更新函数,从而不必让定时器闭包读取某个 count 快照。如果配置只在同步内部使用,也可以把配置构造移进 Effect,直接依赖它的业务字段。每种改法都改变了实际读取关系,随后依赖数组才能相应变化。

普通模块常量不属于每次渲染变化的输入,但随意修改的全局变量也不会自动通知 React。组件外部可变数据需要订阅协议,而不是靠依赖数组轮询。对于自定义同步 Hook,还应配置适当的依赖检查,并检查封装是否把调用方真正需要声明的输入隐藏掉了。

回答前,多想一步

容易答错的地方

工具不了解业务,直接禁用规则最省事
工具确有静态分析边界,但警告经常指出真实的旧闭包问题。应先写清楚为什么某个变化不应重新同步,并让代码表达这个区别,再处理确实无法由工具识别的情况。
把全部 state 都加入依赖最安全
依赖应对应实际读取,不是整个组件状态清单。无关输入会制造不必要同步,也可能掩盖一个 Effect 混合多个职责的问题;需要完整,但不应随意扩大。
试着用自己的话回答

面试官还会怎么问?

setter 为什么经常可以不写进依赖?

React 提供的 state setter 具有稳定身份,依赖检查能够识别某些稳定值,允许省略时可以省略。自定义包装函数或父层传来的函数不能自动套用同样结论。

把最新值放 ref 就一定解决旧闭包吗?

它可以表达某些命令式读取,但也可能绕过必要重同步并增加手动维护。先判断读最新值与因值变化重新连接是否是不同需求,再选择适当机制,避免把所有依赖都藏进 ref。

useEffectEvent 可以在点击事件里调用吗?

它用于 Effect 相关逻辑,不是普通事件处理器的替代品,也不应作为 prop 任意传递。需要用户点击触发的操作应使用正常事件流程,具体约束按项目所用 React 与检查工具版本确认。

从一道题,走向一组知识

把知识连起来

副作用与同步

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

依赖完整后若仍频繁执行,进一步检查对象与函数的构造位置。

副作用与同步

用户点击触发的逻辑为什么通常放事件处理器,而不是 useEffect?

不需要持续同步的用户命令,适合直接放回事件处理流程。

参考资料

  • exhaustive-deps
  • Removing Effect Dependencies
  • React useEffectEvent

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

本题目录
  1. 先记住这个答案
  2. 漏掉文档 ID 为什么会显示旧订阅结果
  3. 把独立同步和事件读取分开
  4. 减少依赖应通过证明代码不再读取它
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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