当前位置: 首页 > news >正文

React@16.x(29)useRef

目录

  • 1,介绍
  • 2,和 React.createRef() 的区别
  • 3,计时器的问题

目前来说,因为函数组件每次触发更新时,都会重新运行。无法像类组件一样让一些内容保持不变。
所以才出现了各种 HOOK 函数:useStateuseCallbackuseMemo 等来辅助实现和类组件相似的功能。

useRef 也是这样的目的。

1,介绍

在之前的文章中介绍了 ref,用于获取组件或真实DOM元素的引用。

useRef 作用相同,不过可以在函数组件中使用。同时它会返回对象的固定引用。

换句话说,当函数组件重新运行时,useRef() 前后2次返回的对象引用地址相同。
一个节点(React元素)对应一个唯一的对象。

React.createRef() 使用举例:

import React, { useState } from "react";export default function App() {const refInput = React.createRef();return (<><input ref={refInput}></input><buttononClick={() => {console.log(refInput.current.value);}}>获取 inputRef</button></>);
}

换成 useRef仅需要替换一行代码:

const refInput = React.createRef();
// 替换为
const refInput = useRef();

2,和 React.createRef() 的区别

上面的代码中,看起来只是一行代码的区别,但本质上处理逻辑不同。

  • React.createRef(),如果 ref 的值发生变动(函数组件重新渲染),则将旧值设为 null
  • useRef(),函数组件重新渲染多次时,所有返回的对象的引用地址相同。

验证下:
简单修改下,将每次更新后的新 ref 放到 window 对象中对比下:

import React, { useRef, useState } from "react";window.arr = [];
export default function App() {const refInput = React.createRef();window.arr.push(refInput);const [n, setN] = useState(); // 只是为了重新渲染组件。return (<><inputref={refInput}type="text"value={n}onChange={(e) => {setN(e.target.value);}}/></>);
}

多次改变 input.value 时,检查 window.arr

在这里插入图片描述

替换为 const refInput = useRef();

在这里插入图片描述

3,计时器的问题

在之前介绍 useEffect 时,提到了下面的写法是有问题的。

因为 useEffect 只会执行一次,所以在计时器中通过闭包获取的状态变量 n 永远都是10,

export default function App() {const [n, setN] = useState(10);useEffect(() => {const timer = setInterval(() => {setN(n - 1);}, 1000);return () => {clearInterval(timer);};}, []);return <div>{n}</div>;
}

该问题,通过将依赖项 n 传入即可。但会引起另一个问题:
每次函数重新运行,都会再次执行 useEffect,开启计时器又销毁计时器,开销很大。

export default function App() {const [n, setN] = useState(10);useEffect(() => {const timer = setInterval(() => {setN(n - 1);}, 1000);return () => {clearInterval(timer);};}, [n]);return <div>{n}</div>;
}

所以,可通过 useRef 来将函数重新运行后的新值传递给计时器,同时 useEffect 也只会运行一次,开启一次计时器!

注意,useRef() 返回的虽然是同一个对象,但 setN 修改的是它的 current 属性。所以计时器每次获取的都是新值。

export default function App() {const [n, setN] = useState(10);const refN = useRef(n);useEffect(() => {const timer = setInterval(() => {setN(--refN.current);}, 1000);return () => {clearInterval(timer);};}, []);return <div>{n}</div>;
}

以上。

相关文章:

  • 用python把docx批量转为pdf
  • [Rust] 求Vec中的最值、统计特定值的数量和统计数组总和
  • 软设之需求分析的工具
  • C++格式化库fmt使用方法
  • win10下使用docker和VMware
  • 高考毕业季--浅谈自己感想
  • 基于PPO的强化学习超级马里奥自动通关
  • 【Python】数据处理:Matplotlib绘图
  • mysql和redis的双写一致性问题
  • Qt | QDataStream 类(数据流)
  • 敏捷=996/007?现实是……
  • 【通过新能源汽车的智慧数字底盘技术看计算机的相关技术堆栈?以后是软硬结合的全能程序员的天下,取代全栈(前后端都会的全栈程序员)】
  • 怎么做才能推动产业园区的数字化转型和升级
  • 独孤思维:每天做着自己不喜欢的工作,你不难受吗
  • uniapp面试题
  • C++类中的特殊成员函数
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • ES6语法详解(一)
  • GitUp, 你不可错过的秀外慧中的git工具
  • JAVA 学习IO流
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • PAT A1092
  • rc-form之最单纯情况
  • Sublime Text 2/3 绑定Eclipse快捷键
  • vue 个人积累(使用工具,组件)
  • 初识MongoDB分片
  • 面试遇到的一些题
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 一文看透浏览器架构
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #DBA杂记1
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (+4)2.2UML建模图
  • (2)MFC+openGL单文档框架glFrame
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (二)PySpark3:SparkSQL编程
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (一)插入排序
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)winform之ListView
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • .Family_物联网
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net 微服务 服务保护 自动重试 Polly
  • .NET6 命令行启动及发布单个Exe文件
  • .NET中winform传递参数至Url并获得返回值或文件
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • [ 隧道技术 ] 反弹shell的集中常见方式(二)bash反弹shell
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [Android] Binder 里的 Service 和 Interface 分别是什么
  • [APIO2015]巴厘岛的雕塑