96SEO 2026-04-23 03:21 1
Ru果你是一名长期奋战在一线的 React 开发者,想必对 TypeScript 配合 React 开发时的那种“爱恨交织”的感觉并不陌生。尤其是当我们面对 React 19 的geng新日志时大多数人可Nengdou在关注 Compiler、Server Components 或者是新的 Actions。但Ru果你仔细翻阅那些kan似不起眼的 Type Script 改动,你会发现一个被社区吐槽了整整五年的“顽疾”终于要被根除了。

这不仅仅是一次简单的类型定义修正,geng像是一场关于“所有权”的哲学辩论。今天我们就来聊聊 React 19 中对 useRef 的修复,kankan这个让无数人被迫写出 as any 的设计,究竟是如何一步步走向终结的。
让我们先回到那个令人窒息的编码场景。你正在写一个组件,逻辑hen清晰:你需要获取一个 DOM 元素的引用,同时你又想在这个 ref 上挂载一些自定义的数据。代码写到一半,TypeScript 的红线就像一道闪电劈了下来:
const myRef = useRef;
// ... 一些逻辑之后
myRef.current = someValue; // 报错!无法赋值给 'current',因为它是只读属性。
这时候,你的第一反应是什么?困惑?愤怒?还是熟练地打开浏览器搜索解决方案?这并非你的代码逻辑有误,而是你撞上了 React 类型系统中一堵名为“保护”的墙。在hen长一段时间里开发者们被逼无奈,只Neng通过类型断言来规避这个实际上并不存在的问题。这种为了安抚类型检查器而牺牲代码优雅性的Zuo法,在社区里简直成了某种“潜规则”。
“所有权”模型的遗产:一场源自 Rust 的浪漫要理解为什么会发生这种事,我们必须把时间拨回到 Hooks 刚刚诞生的年代。那时候,React 团队对于类型系统的设计有着非常宏大的愿景。他们试图在 JavaScript 这种动态语言中,引入一种类似 Rust 或 C++ 的“指针所有权”模型。
这个模型的核心逻辑非常理性,甚至Ke以说有些过于理想化。它认为 ref 应该被严格区分为两种截然不同的角色:
第一种是JSX 引用。当你把一个 ref 挂载到 上时这个 ref 的控制权实际上移交给了 React。React 负责在组件挂载时写入 DOM 节点,在卸载时重置为 null。既然是 React 在管理,那么作为用户的你,理论上不应该去修改它,所以它应该是“只读”的。
第二种是实例变量。当你用 useRef 来存储定时器 ID、或者某个不需要触发重渲染的状态时这个 ref 完全由你掌控。你想怎么改就怎么改,所以它应该是“可变”的。
听起来hen完美,对吧?通过类型系统来防止开发者误操作 React 管理的引用,这简直是类型安全的典范。但现实往往比理论要骨感得多。
类型推导的迷宫:TypeScript 的两难抉择为了实现这种区分,React 的类型定义中埋下了一套非常复杂的重载逻辑。TypeScript 编译器会像侦探一样,根据你传入的初始值和泛型参数,来推断这个 ref 到底属于哪一类。
这就导致了一个非常微妙的情况。Ru果你写 useRef,你传递了一个 null 作为初始值,但在泛型参数里并没有明确包含 | null。在 React 的旧逻辑kan来这传递了一个信号:你想要一个指向 DOM 元素的引用,而且初始值是空的。既然是 DOM 引用,那就归 React 管,那就得是 readonly 的。
于是RefObject 接口中的 current 被标记为了 readonly。这直接导致了前文提到的那个赋值错误。你明明拥有这个对象的引用,却因为类型定义的“过度保护”,失去了修改它的权利。
Ru果这只是个人项目中的小插曲,那也就罢了。但随着 React 生态的繁荣,这种设计开始阻碍基础设施的建设。Zui典型的例子就是组件库中的 forwardRef 和 Ref 合并逻辑。
想象一下你在开发一个 UI 组件库。你需要把父组件传进来的 ref 和组件内部自己用的 ref 合并在一起,以便同时暴露给外部和内部使用。这是一个非常标准且必要的需求。你可Neng会写一个类似 useCombinedRefs 的工具函数:
export const useCombinedRefs = => {
return useCallback => {
refs.forEach(ref => {
if return;
if {
ref;
} else {
// 这里!这里就是战场!
ref.current = element;
}
});
}, refs);
};
在旧有的类型定义下ref.current = element 这一行代码会疯狂报错。因为 TypeScript 认为 ref 可Neng是一个 RefObject,也就是只读的。你无法保证外部传来的 ref 一定是可写的,你也无法强制所有调用方dou按照你的意愿去定义泛型。
这导致了一个荒谬的现状:为了写出类型正确的代码,组件库开发者不得不大量使用类型断言,或者绕过类型检查。原本旨在“确保正确使用”的设计,反而成了阻碍正确使用的绊脚石。
社区的觉醒:从“这是特性”到“这是 Bug”其实关于这个问题的讨论从未停止过。早在几年前,就有开发者在 GitHub 上提出质疑,认为这种区分在 JavaScript 的世界里显得水土不服。有人建议,Ru果 useRef 没有传初始值,就默认当作是 JSX 引用;Ru果传了初始值,就当作是实例变量。
这个建议听起来hen符合直觉,但hen快就被否决了。因为早期的文档中充斥着不带初始值的
当时React 团队中也有成员坚定地维护 这种解释在逻辑上是自洽的。但在实际工程中,它要求所有开发者dou必须对这套复杂的重载规则了如指掌。这显然是一种不切实际的奢望。 直到 2024 年,一条推文
将这个陈年旧账翻了出来。这一次风向变了。大家意识到,所谓的“所有权”模型ref 的读写边界是模糊的,是共享的。 Matt 的那条推文并没有提出什么新 Bug,它只是把那个Yi经被生态长期用“类型断言”掩盖的问题,赤裸裸地摆在了台面上。人们开始反思:我们真的需要这种强制的区分吗?为了一个理论上可Neng存在的错误,我们让 99% 的正常代码dou变得痛苦,这值得吗? 于是关于“让所有 ref 可写”的 RFC项目正式启动。始于几年前的话题,终于在 React 19 的开发周期内迎来了彻底的翻案。 React 19 Zui终选择了妥协,或者说选择了实用主义。它决定废除那个令人费解的 这意味着,在 React 19 的类型定义中, 这不仅仅是修复了一个 TypeScript 报错,geng是 React 团队对“开发者体验”的一次重要让步。他们承认,在 JavaScript 这种灵活的语言中,过度严格的类型约束有时反而会适得其反。与其试图教开发者怎么写代码,不如相信开发者的判断,给他们足够的自由度。 回过头来kan,React 19 修复这个 bug 的过程确实有些曲折。从Zui初的雄心勃勃,试图引入系统编程语言的“所有权”概念,到后来被社区的各种实际场景“打脸”,Zui后不得不推翻重来这中间耗费了数年的时间。 但这并不是浪费时间。这个过程让我们geng深刻地理解了 React 的运行机制,也让我们kan到了类型系统设计的复杂性。那个曾经被认为是“优雅设计”的 React 19 的这次改动,就像是卸下了一副沉重的铠甲。虽然少了一些理论上的“安全感”,但却让开发者的动作变得geng加轻盈、自如。对于每一个曾经被 所以React 19 修复旧 bug 的过程曲折吗?曲折。但正是这种曲折,才孕育出了geng成熟、geng贴近人性的解决方案。毕竟工具的本质是为人服务的,而不是让人去迁就工具的。useRef 用法,Ru果贸然改变语义,破坏性太大。而且,readonly 的设计。他们认为,这是一种优雅的约束,Neng防止开发者犯下“在 React 管理的 ref 上乱写数据”的错误。Ru果你真的需要一个可写的 ref,并且初始值是 null,那你就在泛型里老老实实加上 | null,比如 useRef。这样 TypeScript 就会根据“Zui佳匹配原则”,返回一个 MutableRefObject。readonly 限制。useRef 将不再试图去猜测你是想把它当 DOM 引用还是实例变量。所有的 ref,在类型层面dou将被视为可变的。你不再需要为了给 current 赋值而绞尽脑汁地去构造泛型参数,也不再需要写那些丑陋的类型断言。readonly 方案,虽然在理论上无懈可击,但在充满变数的实际开发中,却显得格格不入。Cannot assign to 'current' because it is read-only 折磨过的开发者来说这无疑是一个值得庆祝的时刻。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback