深聊 useRef:比你知道的再多一点
用 ref 偷看 DOM 的“底牌”用 ref 存储“不渲染”的秘密大家好在日常开发中useState和useEffect几乎是我们的“肌肉记忆”但useRef这个 Hook 却常常被简化成一个“DOM 获取器”。今天带你重新认识这位“熟悉的陌生人”。你会发现useRef不仅仅是document.getElementById的 React 替代品它更是 React 渲染机制里一个巧妙的“后门”。1. 从“为什么需要 Ref”说起在 React 的世界里我们提倡“数据驱动视图”意思是你只管改数据UI 会自己变。这让我们告别了过去“命令式”的 DOM 操作比如document.getElementById(input).focus()极大地提升了开发效率和性能。但“完全禁止操作 DOM”是不现实的。React 官方也清楚这一点于是提供了useRef这个 Hook让我们在必要时可以“抓住”真实的 DOM 节点。1.1 回顾一下 DOM 操作的代价在 React 和 Vue 出现之前我们直接用 JS 操作 DOM。JS 引擎V8和渲染引擎是分离的每次 JS 访问 DOM 都是一次“跨界”。这种跨引擎的通信是有性能开销的。所以 React 的“虚拟 DOM”和“批量更新”本质上就是为了减少这种跨界的频率。说白了就是React 推荐你用state控制 UI而不是自己手动改 DOM。但如果非要去改请走useRef这个“官方通道”。2.useRef的两大核心场景我把useRef的用法抽象为两类绑定 DOM 节点和存储可变数据。虽然它们底层原理一样但使用场景截然不同。2.1 场景一绑定 DOM 节点“连接”真实世界这是useRef最基础的应用。比如我们想让输入框在页面加载后自动获得焦点。代码示例自动聚焦import React, { useRef, useEffect } from react; const LoginInput () { // 1. 声明一个 ref 对象初始值为 null const inputRef useRef(null); // 2. 在组件挂载完成后手动聚焦 useEffect(() { // 此时 inputRef.current 就是真实的 input DOM 元素 if (inputRef.current) { inputRef.current.focus(); } }, []); // 空依赖数组确保只执行一次 return ( // 3. 通过 ref 属性将 DOM 节点挂载到 inputRef.current 上 input ref{inputRef} typetext placeholder用户名 / ); };深度解析useRef(null)创建了一个对象{ current: null }。当 React 将input渲染到真实 DOM 后会在“提交阶段”commit phase更新inputRef.current的指向。useEffect在 DOM 绘制完成后执行所以我们能在其中安全地操作inputRef.current。2.2 场景二存储可变数据“跨渲染”的容器这是useRef最容易被忽略但极其强大的功能。它像是一个组件实例上的“全局变量”可以用来存储任何可变值并且改变它不会触发组件重新渲染。代码示例记录点击次数import React, { useRef, useState } from react; const ClickCounter () { // 定义一个类似“全局变量”的计数器 const countRef useRef(0); // 这个 state 只用来“强制”触发渲染它的值不重要 const [, setDummy] useState(0); const handleClick () { // 修改 ref.current 不会触发渲染 countRef.current 1; console.log(点击次数, countRef.current); // 手动触发一下渲染以便看到 UI 上的变化虽然我们用 ref 存值 setDummy(prev prev 1); }; return ( div {/* 你会发现即使 setDummy 触发了渲染countRef.current 的值依然保持不变 */} p点击次数用 ref 存储{countRef.current}/p button onClick{handleClick}增加/button /div ); };useState是给 React看的变了它就得干活渲染useRef是给你自己用的怎么变都行别打扰 React。2.3useRefvsuseState核心差异为了让你更清晰我整理了一个对比表格特性useStateuseRef更新方式setXxx(newValue)ref.current newValue触发渲染会更新后重绘不会静默修改存储内容用于渲染的数据UI 状态不用于渲染的数据副作用、实例变量读取时机渲染期间读取任何时候事件、Effect、定时器典型用途表单输入、控制显示隐藏DOM 引用、定时器 ID、跨渲染变量3. 进阶useRef的“不变”原理底层触发机制深度解析你可能会好奇为什么useRef修改值不会触发渲染而setState一改就立刻重绘而且为什么useRef能在多次渲染之间保持同一个引用答案就在它的“出生地”和 React 的任务调度机制里。useRef实际上是在 React 的“内部 Fiber 节点”上挂载了一个属性。每次组件函数执行渲染时useRef返回的都是同一个内存地址的对象。React 只会在首次渲染时初始化current属性后续渲染直接复用。但更深层次的区别在于 React 的“更新队列”和“调度中心”是如何看待这两个 Hook 的useState的“强制唤醒”机制当你调用setCount时React 会做两件非常重的事情。首先它会在该 Fiber 节点的更新队列updateQueue中创建一个更新对象Update Object其次它会向 React 的调度器Scheduler发起一个“优先级任务”请求。这个任务会强制组件重新执行Re-render哪怕你的新值和旧值一模一样除非使用了updater函数做惰性判断。重新执行后React 会走完完整的“调度 - 协调Diffing- 提交Commit”流水线。useRef的“静默修改”机制当你修改ref.current时你仅仅是在直接修改 Fiber 节点memoizedState中的一个普通 JavaScript 对象属性。关键在于这个突变Mutation完全绕过了 React 的状态更新机制。因为没有新的 Update 对象被创建调度器的任务队列空空如也React 根本感知不到这个变化。在 React 的理念里“没有 Update 就意味着没有状态变化既然状态没变那就没有重新渲染的必要”。换个更形象的比喻useState的setter像是你在公司群里了全体成员React并大喊“出大事了快开会重新渲染”而修改useRef.current就像是你默默在自己的工位笔记本上涂改了一笔老板React根本不知道自然也不会组织全员大会。这种机制带来的最大好处就是极致的性能优化。如果你的组件需要频繁记录一些“与 UI 无关”的数据比如滚动事件的节流标记、动画的帧率计数器、定时器的 ID使用useRef可以确保这些高频操作完全不影响 React 的主渲染线程从而避免掉帧和无意义的计算。4. 常见踩坑与最佳实践4.1 不要在渲染过程中读写ref.current// ❌ 错误示例 const App () { const ref useRef(0); // 在渲染函数中修改 ref会导致不可预测的结果甚至破坏并发渲染 ref.current ref.current 1; return div{ref.current}/div; };最佳实践只在事件处理函数、useEffect或setTimeout等“副作用”中操作ref.current。4.2 用ref来“缓存”函数或定时器有时候我们需要在组件卸载时清除定时器。用useRef来存储定时器 ID 是最优雅的方式。const Timer () { const timerIdRef useRef(null); const startTimer () { timerIdRef.current setInterval(() { console.log(tick); }, 1000); }; const stopTimer () { clearInterval(timerIdRef.current); }; // 在组件卸载时清理 useEffect(() { return () { if (timerIdRef.current) { clearInterval(timerIdRef.current); } }; }, []); // ... return JSX with buttons };4.3 别把所有东西都往ref里放useRef是用来存放“副作用”的不是用来存业务数据的。如果你发现某个值需要被 UI 展示那它必须是 State如果某个值的变化需要 UI 响应那它也必须是 State。一句话总结UI 要用的用useStateUI 不关心的用useRef。5. 总结useRef是 React 设计中非常精妙的一环。它既是我们与命令式 DOM 操作之间的桥梁也是我们绕过 React 响应式系统的一个“安全通道”。通过今天的文章希望你能记住三点用ref抓 DOM替代document.querySelector在useEffect中操作。用ref存变量存储那些“变了也不需要重新渲染”的数据。牢记不变性useRef在整个生命周期中保持引用不变这是其所有特性的基石。下次当你再次写下useRef时别忘了你正在使用 React 赋予你的“超能力”去窥探和影响那个响应式世界之外的物理空间。

相关新闻

2026年面试题(一)

2026年面试题(一)

一、前端都有哪些技术1)基础三层HTML:页面结构,标签搭建页面骨架CSS:页面样式,布局、颜色、动画;衍生:CSS3、SCSS/Sass、Less、Tailwind CSSJavaScript:页面交互逻辑;ES6…

2026/8/9 12:58:11 阅读更多 →
AI绘图工具实战指南:从Mermaid到Draw.io,重构技术图表工作流

AI绘图工具实战指南:从Mermaid到Draw.io,重构技术图表工作流

1. 从“手动画图”到“AI驱动”:一次工作流的彻底革新如果你和我一样,曾经为了画一张清晰的技术架构图、业务流程图或者系统部署图,在 Draw.io、Visio 甚至 PPT 里耗费数小时,反复调整框线、对齐箭头、斟酌配色,最后出…

2026/8/9 15:14:42 阅读更多 →
OpenClaw实战:从零部署AI Agent框架,实现自然语言驱动应用开发

OpenClaw实战:从零部署AI Agent框架,实现自然语言驱动应用开发

1. 从“手动挡”到“自动驾驶”:AI开发范式的革命性转变如果你是一名开发者,或者对AI应用开发感兴趣,那么最近一定被“AI Agent”、“智能体”这些词刷屏了。传统的AI应用开发是什么样子的?那感觉就像开一辆“手动挡”的老爷车。你…

2026/8/9 18:34:23 阅读更多 →

最新新闻

钓鱼邮件伪装技术解析与企业防御实战指南

钓鱼邮件伪装技术解析与企业防御实战指南

1. 钓鱼邮件新变种:伪装成垃圾邮件警报的攻击手法剖析最近安全团队发现一类高度定向化的钓鱼攻击,攻击者精心伪造企业级垃圾邮件过滤系统的警报通知,诱导受害者点击恶意链接。这类邮件通常带有"您的邮件已被隔离"、"重要&…

2026/8/10 3:19:37 阅读更多 →
老年公寓管理系统开发:SpringBoot+Vue技术实践

老年公寓管理系统开发:SpringBoot+Vue技术实践

## 1. 项目背景与核心价值"夕阳红公寓管理系统"这个命名已经透露了项目的服务对象——老年公寓。随着人口老龄化加剧,专门针对老年群体的智慧化管理需求正在快速增长。这类系统需要特别考虑老年人的使用习惯(如大字体界面、简化操作流程&#…

2026/8/10 3:19:37 阅读更多 →
SpringBoot+Vue养老公寓管理系统开发实践

SpringBoot+Vue养老公寓管理系统开发实践

1. 项目概述:夕阳红公寓管理系统的技术架构与价值夕阳红公寓管理系统是一款面向养老机构的管理软件,采用前后端分离架构实现。后端基于Java技术栈构建,使用SpringBoot框架简化开发流程,MyBatis作为持久层框架;前端采用…

2026/8/10 3:19:37 阅读更多 →
TypeScript开发环境搭建:从零配置到热重载实战指南

TypeScript开发环境搭建:从零配置到热重载实战指南

如果你刚开始学习 TypeScript,可能会遇到一个看似简单却让人困惑的问题: 为什么我明明安装了 TypeScript,却还是无法运行 .ts 文件? 或者,你按照教程配置了 tsconfig.json ,但编译时总提示各种奇怪的…

2026/8/10 3:19:37 阅读更多 →
区域能源系统鲁棒优化:应对多能负荷不确定性的实践

区域能源系统鲁棒优化:应对多能负荷不确定性的实践

1. 项目背景与核心挑战区域综合能源系统(RIES)规划是当前能源互联网建设的关键环节。我在参与某工业园区能源系统升级项目时,深刻体会到传统确定性规划方法的局限性——当风光发电出力波动超过预期20%时,原设计方案的经济性指标直…

2026/8/10 3:19:37 阅读更多 →
Unity光线反射与折射实战:从向量推导到递归追踪实现

Unity光线反射与折射实战:从向量推导到递归追踪实现

1. 项目概述:为什么要在游戏里“玩”光线?做游戏开发这么多年,我始终觉得,能让一个虚拟世界“活”起来的,除了精妙的玩法和动人的故事,就是那些看似不起眼,却无处不在的物理细节。其中&#xff…

2026/8/10 3:18:37 阅读更多 →

日新闻

GraphQL-CSS API全解析:useGqlCSS、GqlCSS组件与getStyles实用指南

GraphQL-CSS API全解析:useGqlCSS、GqlCSS组件与getStyles实用指南

GraphQL-CSS API全解析:useGqlCSS、GqlCSS组件与getStyles实用指南 【免费下载链接】graphql-css A blazing fast CSS-in-GQL™ library. 项目地址: https://gitcode.com/gh_mirrors/gr/graphql-css GraphQL-CSS是一个基于GraphQL的CSS-in-GQL™库&#xff0…

2026/8/10 0:00:02 阅读更多 →
告别语言障碍:KISS Translator 双语翻译插件终极指南

告别语言障碍:KISS Translator 双语翻译插件终极指南

告别语言障碍:KISS Translator 双语翻译插件终极指南 【免费下载链接】kiss-translator A simple, open source bilingual translation extension & Greasemonkey script (一个简约、开源的 双语对照翻译扩展 & 油猴脚本) 项目地址: https://gitcode.com/…

2026/8/10 0:00:02 阅读更多 →
BepInEx配置管理器:游戏插件配置的终极可视化解决方案

BepInEx配置管理器:游戏插件配置的终极可视化解决方案

BepInEx配置管理器:游戏插件配置的终极可视化解决方案 【免费下载链接】BepInEx.ConfigurationManager Plugin configuration manager for BepInEx 项目地址: https://gitcode.com/gh_mirrors/be/BepInEx.ConfigurationManager 你是否曾经因为游戏插件的复杂…

2026/8/10 0:00:02 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/10 1:05:29 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/10 1:05:29 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/10 1:05:29 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/9 17:05:02 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/10 1:05:29 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/9 17:05:02 阅读更多 →