精读《useRef 与 createRef 的区别》

1 引言

useRef 是常用的 API,但还有一个 createRef 的 API,你知道他们的区别吗?通过 React.useRef and React.createRef: The Difference 这篇文章,你可以了解到何时该使用它们。

2 概述

其实原文就阐述了这样一个事实:useRef 仅能用在 FunctionComponent,createRef 仅能用在 ClassComponent。

第一句话是显然的,因为 Hooks 不能用在 ClassComponent。

第二句话的原因是,createRef 并没有 Hooks 的效果,其值会随着 FunctionComponent 重复执行而不断被初始化:

function App() {
  // 错误用法,永远也拿不到 ref
  const valueRef = React.createRef();
  return <div ref={valueRef} />;
}

上述 valueRef 会随着 App 函数的 Render 而重复初始化,这也是 Hooks 的独特之处,虽然用在普通函数中,但在 React 引擎中会得到超出普通函数的表现,比如初始化仅执行一次,或者引用不变

为什么 createRef 可以在 ClassComponent 正常运行呢?这是因为 ClassComponent 分离了生命周期,使例如 componentDidMount 等初始化时机仅执行一次。

原文完。

3 精读

那么知道如何正确创建 Ref 后,还知道如何正确更新 Ref 吗?

由于 Ref 是贯穿 FunctionComponent 所有渲染周期的实例,理论上在任何地方都可以做修改,比如:

function App() {
  const valueRef = React.useRef();

  valueRef.current += 1;

  return <div />;
}

但其实上面的修改方式是不规范的,React 官方文档里要求我们避免在 Render 函数中直接修改 Ref,请先看下面的 FunctionComponent 生命周期图:

从图中可以发现,在 Render phase 阶段是不允许做 “side effects” 的,也就是写副作用代码,这是因为这个阶段可能会被 React 引擎随时取消或重做。

修改 Ref 属于副作用操作,因此不适合在这个阶段进行。我们可以看到,在 Commit phase 阶段可以做这件事,或者在回调函数中做(脱离了 React 生命周期)。

当然有一种情况是可以的,即 懒初始化:

function Image(props) {
  const ref = useRef(null);

  // ✅ IntersectionObserver is created lazily once
  function getObserver() {
    if (ref.current === null) {
      ref.current = new IntersectionObserver(onIntersect);
    }
    return ref.current;
  }

  // When you need it, call getObserver()
  // ...
}

懒初始化的情况下,副作用最多执行一次,而且仅用于初始化赋值,所以这种行为是被允许的。

为什么对副作用限制的如此严格?因为 FunctionComponent 增加了内置调度系统,为了优先响应用户操作,可能会暂定某个 React 组件的渲染,具体可以看第 99 篇精读:精读《Scheduling in React》

Ref 不仅可以拿到组件引用、创建一个 Mutable 副作用对象,还可以配合 useEffect 存储一个较老的值,最常用来拿到 previousProps,React 官方利用 Ref 封装了一个简单的 Hooks 拿到上一次的值:

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

由于 useEffect 在 Render 完毕后才执行,因此 ref 的值在当前 Render 中永远是上一次 Render 时候的,我们可以利用它拿到上一次 Props:

function App(props) {
  const preProps = usePrevious(props);
}

要实现这个功能,还是要归功于 ref 可以将值 “在各个不同的 Render 闭包中传递的特性”。最后,不要滥用 Ref,Mutable 引用越多,对 React 来说可维护性一般会越差。

4 总结

你还挖掘了 useRef 哪些有意思的使用方式?欢迎在评论区留言。

讨论地址是:精读《useRef 与 createRef 的区别》 · Issue #236 · dt-fe/weekly

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/473555.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ICT产品供应链安全现状分析与对策建议

本文尝试分析ICT产品供应链的安全背景、政策法规&#xff0c;并给出具体针对性的建议供ICT产品供应链的供需双方参考。 当今网络安全威胁和攻击的形式正在发生深刻的变化&#xff0c;已经从传统的网络安全领域逐渐扩展到供应链安全方向。ICT&#xff08;信息通信技术&#xff…

[Qt学习笔记]Qt实现鼠标点击或移动时改变鼠标的样式以及自定义鼠标样式

1、鼠标样式介绍以及对应函数 在Qt中大概有20种左右的内置鼠标样式&#xff0c;一般使用setCursor(Qt::CursorShape shape)来进行设置&#xff0c;一般常用的有标准箭头、手型&#xff0c;双箭头等等形状&#xff0c;对于不同的操作系统下&#xff0c;鼠标的样式显示会略有差别…

2.Labview字符串与路径精讲(上) — 理论篇

本章讲解labview中的字符串和路径及其使用方法&#xff0c;从前面板字符串属性到后面板字符串函数应用做出详细概述&#xff0c;通过本文的学习希望大家了解到字符串在labview编程中的重要地位。 本系列文章为labview 从基础到强化到精通的学习文章&#xff0c;大家可以随时点进…

《Adaptive Adversarial Patch Attack on Face Recognition Models》论文分享(侵删)

原文地址&#xff1a;Adaptive Adversarial Patch Attack on Face Recognition Models | IEEE Conference Publication | IEEE Xplore author{Bei Yan and Jie Zhang and Zheng Yuan and Shiguang Shan}, title{Adaptive Adversarial Patch Attack on Face Recognition Models…

springcloud-Eureka注册中心

如果你要理解这个技术博客博客专栏 请先学习以下基本的知识&#xff1a; 什么是微服务什么是服务拆分什么是springcloud Springcloud为微服务开发提供了一个比较泛用和全面的解决框架&#xff0c;springcloud继承了spring一直以来的风格——不重复造轮子&#xff0c;里面很多的…

c++ 指针大小

C的一个指针占内存几个字节&#xff1f; 结论&#xff1a; 取决于是64位编译模式还是32位编译模式&#xff08;注意&#xff0c;和机器位数没有直接关系&#xff09; 在64位编译模式下&#xff0c;指针的占用内存大小是8字节在32位编译模式下&#xff0c;指针占用内存大小是4字…

JavaScript 使用 Promise 实现 sleep 休眠

以下为代码实现&#xff0c;该代码实现了每隔1秒打印一次当前时间&#xff0c;总共打印5次的功能 for(let i 1; i < 5; i){console.log(new Date().toString())await new Promise(resolve>setTimeout(resolve,1000)) }实现休眠的核心代码为: await new Promise(resolv…

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-LSTM雪消融…

使用el-cascader组件写下拉级联多选并且具有全选功能

样式 说明&#xff1a; 级联选择器中加上全选的按钮&#xff0c; 并且保证数据响应式。 思路 因为是有全选的功能&#xff0c;所以不能直接使用el-cascader组件&#xff0c; 而是选择使用el-select组件&#xff0c; 在此组件内部使用el-cascader-panel级联面板全选按钮也是…

【机器学习】科学库使用第2篇:机器学习概述,学习目标【附代码文档】

机器学习&#xff08;科学计算库&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习&#xff08;常用科学计算库的使用&#xff09;基础定位、目标&#xff0c;机器学习概述定位,目标,学习目标,学习目标。机器学习概述&#xff0c;1.3 人…

idea-不同项目使用不同maven版本

背景 idea一直使用的是maven3.6. 新接的项目要求maven要3.9&#xff0c;所以down下来以后maven的dependencies一直加载失败。 报错信息为 Full classname legend:CustomModelValidator: "org.jetbrains.idea.maven.server.embedder.CustomModelValidator" DefaultM…

RabbitMQ--03--SpringAMQP(SpringBoot集成RabbitMQ)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SpringAMQP1.SpringBoot 的支持https://spring.io/projects/spring-amqp 2.RabbitTemplate3.RabbitListener&#xff08;终极监听方案&#xff09;4.RabbitConfig--…

用pdf2docx将PDF转换成word文档

pdf2docx是一个Python模块&#xff0c;可以将PDF文件转换为docx格式的Word文档。 pdf2docx模块基于Python的pdfminer和python-docx库开发&#xff0c;可以在Windows、Linux和Mac系统上运行。它可以从PDF文件中提取文本和图片&#xff0c;并将其转换成可编辑的Word文档&#xf…

Photoshop 2024让图像处理更智能、更高效@

Photoshop 2024是一款功能强大的图像处理软件&#xff0c;广泛应用于创意设计和图像处理领域。它提供了丰富的绘画和编辑工具&#xff0c;包括画笔、铅笔、颜色替换、混合器画笔等&#xff0c;使用户能够轻松进行图片编辑、合成、校色、抠图等操作&#xff0c;实现各种视觉效果…

CAPL如何实现TCP Packet的option字段

在TCP协议中,主机可以根据自身的需要决定TCP通信时是否携带option字段,来扩展TCP功能。option字段属于TCP首部的扩展部分,且是可选项,TCP根据首部中的offset字段值确定TCP报文是否携带option字段。 TCP首部固定的部分有20个字节,如果没有扩展部分(option字段),20个字节…

万界星空科技铜杆加工行业生产管理MES系统

传统的铜管加工方法有&#xff1a; &#xff08;1&#xff09;铜管挤压加工技术&#xff08;2&#xff09;铜管上引连铸法&#xff08;3&#xff09;铜管(有缝)焊接生产技术&#xff08;4&#xff09;铸轧法生产精密铜管铸轧法 生产精密铜管是一种全新的生产工艺&#xff0c;…

像uniapp image标签一样对图片进行缩放和裁剪

像uniapp image标签一样对图片进行缩放和裁剪 0 前言提示1 实现1.1 不保持纵横比缩放图片&#xff0c;使图片的宽高完全拉伸至填满 image 元素1.2 保持纵横比缩放图片&#xff0c;使图片的长边能完全显示出来。也就是说&#xff0c;可以完整地将图片显示出来。1.3 保持纵横比缩…

git如何在某个commitId的状态提交到一个分支

有些时候&#xff0c;我们在使用子仓库&#xff0c;或者其他情况&#xff0c;会有一个状态是当前的git仓库是在一个commitId上&#xff0c;而没有在一个分支上&#xff1a; 这时如果想要把基于这个commitId创建一个分支&#xff0c;可以使用下面这个命令&#xff1a; git push…

ubuntu20.04搭建rtmp视频服务

1.安装软件 sudo apt-get install ffmpeg sudo apt-get install nginx sudo apt-get install libnginx-mod-rtmp 2.nginx配置 修改/etc/nginx/nginx.conf文件&#xff0c;在末尾添加&#xff1a; rtmp {server {listen 1935;application live {live on;}} } 3.视频测试 本…

OpenAI的GPT已达极限,更看好AI Agent

日前&#xff0c;比尔盖茨发表文章表示&#xff1a;AI Agent不仅会改变人与电脑的互动方式&#xff0c;或许还将颠覆软件行业&#xff0c;引领自输入命令到点击图标以来的最大计算机革命。 在数字化和技术创新的浪潮中&#xff0c;AI Agent作为一种前沿技术&#xff0c;正开启…