【React】ref

概述

使用 ref 引用值 – React 中文文档

希望组件“记住”某些信息,但又不想让这些信息更新时 触发新的渲染 时,可以使用 ref

也就是说 ref 对象 包裹的值 React 追踪不到的,他像是用来存储组件信息的秘密“口袋”。

与 state 相同的是,React 会在每次重新渲染组件之间保留 ref。与 state 不同的是,设置 state 会重新渲染组件,更改 ref 不会!ref 是一个普通的 JavaScript 对象,具有可以被读取和修改的 current 属性(也就是我们初始化的值)。

下面是一个计时器的示例:

需要追踪按下“开始”按钮的时间和当前时间,并用于视图渲染,因此保存在 state 中。

而取消现有的 interval,让它停止更新 now state 变量。需要为其提供 interval ID, 由于 interval ID 不用于渲染,可以将其保存在 ref 中

import {useRef, useState} from "react";function App() {const [startTime, setStartTime] = useState(null)const [now, setNow] = useState(null)const intervalRef = useRef(null);function handleStart() {// 设置开始时间和 当前时间setStartTime(Date.now())setNow(Date.now())// 清除之前可能存在的定时器clearInterval(intervalRef.current)intervalRef.current = setInterval(() => {setNow(Date.now())}, 10)}function handleStop () {clearInterval(intervalRef.current)}let secondsPassed = 0if (startTime && now) {secondsPassed = (now - startTime) / 1000}return (<div className="App"><h1>时间计时器,时间过去了:{secondsPassed.toFixed(3)}s</h1><button onClick={handleStart}>开始</button><button onClick={handleStop}>停止</button></div>);
}export default App;

image.png

ref 和 state 的区别:

refstate
useRef(initialValue)返回 { current: initialValue }useState(initialValue) 返回 state 变量的当前值和一个 state 设置函数 ( [value, setValue])
更改时不会触发重新渲染更改时触发重新渲染。
可变 —— 你可以在渲染过程之外修改和更新 current 的值。“不可变” —— 你必须使用 state 设置函数来修改 state 变量,从而排队重新渲染。
你不应在渲染期间读取(或写入) current 值。你可以随时读取 state。但是,每次渲染都有自己不变的 state 快照。

如果将 useRef的值用于 试图渲染,将会发生什么呢?

可以看到值虽然改变了,但是视图并没有同步更新。

import React, {useRef} from 'react';function ChildCom1(props) {let countRef = useRef(0);function handleClick() {// 这样并未重新渲染组件!countRef.current = countRef.current + 1;console.log(countRef.current)}return (<><h1>这是子组件</h1><button onClick={handleClick}>你点击了 {countRef.current} 次</button></>);
}export default ChildCom1;

image.png

ref 的使用场景:

  • 存储 timeout ID
  • 存储和操作 DOM 元素,我们将在 下一页 中介绍
  • 存储不需要被用来计算 JSX 的其他对象。

如果组件需要存储一些值,但不影响渲染逻辑,选择 ref。

state 就像 每次渲染的快照,并且 不会同步更新。但是当你改变 ref 的 current 值时,它会立即改变。

ref 与 DOM

访问由 React 管理的 DOM 元素 —— 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。需要一个指向 DOM 节点的 ref 来实现。

import React, {useRef} from 'react';function ChildCom2(props) {const inputRef = useRef(null)function handleClick() {inputRef.current.focus()}return (<div><h1>这是子组件2</h1><input ref={inputRef} /><button onClick={handleClick}>聚焦输入框</button></div>);
}export default ChildCom2;

image.png

注意:React 不允许组件访问其他组件的 DOM 节点。甚至自己的子组件也不行!

import { useRef } from 'react';function MyInput(props) {return <input {...props} />;
}export default function MyForm() {const inputRef = useRef(null);function handleClick() {inputRef.current.focus();}return (<><MyInput ref={inputRef} /><button onClick={handleClick}>聚焦输入框</button></>);
}

image.png

image.png

想要 暴露其 DOM 节点的组件必须选择该行为。一个组件可以指定将它的 ref “转发”给一个子组件,使用 forwardRef API。

const MyInput = forwardRef((props, ref) => {return <input {...props} ref={ref} />;
});

image.png

React 中,每次更新都分为 两个阶段:

  • 在 渲染 阶段, React 调用你的组件来确定屏幕上应该显示什么。
  • 在 提交 阶段, React 把变更应用于 DOM。

在第一次渲染期间,DOM 节点尚未创建,因此 ref.current 将为 null。在渲染更新的过程中,DOM 节点还没有更新,所以也不应该在此刻读取 ref。

更新 DOM 后,React 立即将它们设置到相应的 DOM 节点。

切换 dom 节点可以使用 条件渲染 和 state 切换它的显示和隐藏。而ref.current.remove();可以将节点直接从 DOM 中删除。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于uni-app和图鸟UI开发上门服务小程序

一、技术栈选择 uni-app&#xff1a;我们选择了uni-app作为开发框架&#xff0c;因为它基于Vue.js&#xff0c;允许我们编写一次代码&#xff0c;发布到多个平台&#xff0c;包括iOS、Android、Web以及各种小程序。uni-app的丰富组件库、高效的状态管理以及便捷的预览调试功能&…

【PL理论深化】(3) MI 归纳法:归纳假设 (IH) | 结构归纳法 | 归纳假设的证明

&#x1f4ac; 写在前面&#xff1a;所有编程语言都是通过归纳法定义的。因此&#xff0c;虽然编程语言本身是有限的&#xff0c;但用该语言编写的程序数量是没有限制的&#xff0c;本章将学习编程语言研究中最基本的归纳法。本章我们继续讲解归纳法&#xff0c;介绍归纳假设和…

软件设计师笔记-操作系统知识

操作系统的作用 操作系统(Operating System, OS)在计算机系统中扮演着至关重要的角色。通过资源管理提高计算机系统的效率;改善人机界面,向用户提供友好的工作环境。 通过资源管理提高计算机系统的效率: 处理器管理:操作系统负责管理和调度计算机的中央处理器(CPU)资源…

【论文阅读】场景生成及编辑3D定位论文阅读

<div id"content_views" class"htmledit_views" style"user-select: auto;"><div class"kdocs-document"> 前置知识 归纳偏置 关于归纳偏置的理解&#xff1a;首先推荐一篇解释归纳偏置非常好的博客&#xff1a;浅谈归纳…

BASH脚本

先打开一个子bash&#xff0c;然后执行脚本&#xff0c;再退出子bsah { 1.指定解释器的方式 bash ***&#xff08;脚本名或脚本的绝对路径&#xff09; sh ***&#xff08;脚本名或脚本的绝对路径&#xff09; 3.路径方式引用脚本&#xff08;标准的执行命令&#xff0c;需要执…

CEM客户体验管理

客户体验管理&#xff08;Customer Experience Management, CEM&#xff09;智能系统是一种集成 的解决方案&#xff0c;可帮助企业跟踪、分析和管理客户与公司的所有交互&#xff0c;从而提高客户体验和满意度。 系统功能应用 该系统的主要功能有会话质检、客户培训、商品体…

从入门到精通:网络基础(一)

前言 计算机网络是现代信息社会的基石&#xff0c;几乎所有的数字通信和数据交换都依赖于网络。理解网络的基本概念和技术&#xff0c;对于每一个IT从业者来说都是必不可少的。在这篇文章中&#xff0c;我们将从网络的起源和发展开始&#xff0c;逐步深入探讨局域网&#xff0…

Selenium WebDriver - 浏览器交互

本文翻译整理自&#xff1a;https://www.selenium.dev/documentation/webdriver/interactions/ 文章目录 一、获取浏览器信息1、获取头衔2、获取当前URL 二、浏览器导航1、导航到2、后退3、往前4、刷新 三、JavaScript警报、提示和确认1、警报2、确认3、提示 四、使用cookie1、…

STM32学习 修改系统主频

前面时钟树的学习说明单片机的主频是可以修改的&#xff0c;那么怎么更改系统的主频&#xff0c;这里做一个简单的介绍。首先要明白&#xff0c;单片机的程序是如何运行&#xff0c;这里简单说明一下。 对应的代码在startup_stm32....文件里面&#xff0c;这里是复位程序的汇编…

多分类情绪识别模型训练及基于ChatGLM4-9B的评论机器人拓展

你的下一个微博罗伯特何必是罗伯特 这是一篇我在使用开源数据集(Twitter Emotion Dataset (kaggle.com))进行情绪识别的分类模型训练及将模型文件介入对话模型进行应用的过程记录。当通过训练得到了可以输入新样本预测的模型文件后&#xff0c;想到了或许可以使用模型文件对新样…

JavaScript的学习之旅之初始JS

目录 一、认识三个常见的js代码 二、js写入的第二种方式 三、js里内外部文件 一、认识三个常见的js代码 <script>//写入js位置的第一个地方// 控制浏览器弹出一个警告框alert("这是一个警告");// 在计算机页面输入一个内容&#xff08;写入body中&#xff…

【计算机网络仿真实验-实验3.1、3.2】交换路由综合实验

实验3.1 交换路由综合实验——作业1 一、实验目的 运用实验二&#xff08;可前往博主首页计算机网络专栏下查看&#xff09;中学到的知识&#xff0c;将这个图中的PC机连接起来组网并分析&#xff0c;本篇涉及代码以截图展示&#xff0c;过于简单的代码及操作不再详细介绍&…

JAVA特点

Java 的特点如下&#xff1a; 简单性&#xff1a;Java 设计时考虑到了易用性&#xff0c;它的语法相对简洁&#xff0c;并且去掉了一些容易出错的编程元素&#xff0c;比如指针。面向对象&#xff1a;Java 是一种面向对象的编程语言&#xff0c;这意味着它使用类和对象来设计程…

RPC通信原理以及项目的技术选型

目录 1.引言 2、RPC通信原理 3.图示解析 4.再举个例子 1.引言 根据上一篇博客《单机&#xff0c;集群和分布式》的举的例子。 我们最终合理地通过对大型软件的合理划分&#xff0c;划分成不同模块&#xff0c;按需求&#xff08;硬件需求&#xff0c;高并发需求&#xff09…

K8S - 理解ClusterIP - 集群内部service之间的反向代理和loadbalancer

在Micro Service的治理中。 有两个很重要的点&#xff0c; 集群外部的用户/service 如何访问集群内的 入口服务(例如UI service&#xff09;集群内的service A 如何 访问 集群内的service B 为什么有上面的问题 无非是&#xff1a; 集群内的service 都是多实例的每个servic…

【区块链】区块链架构设计:从原理到实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 区块链架构设计&#xff1a;从原理到实践引言一、区块链基础概念1.1 区块链定义…

[系统运维|Xshell]宿主机无法连接上NAT网络下的虚拟机进行维护?主机ping不通NAT网络下的虚拟机,虚拟机ping的通主机!解决办法

遇到的问题&#xff1a;主机ping不通NAT网络下的虚拟机&#xff0c;虚拟机ping的通主机 服务器&#xff1a;Linux&#xff08;虚拟机&#xff09; 主机PC&#xff1a;Windows 虚拟机&#xff1a;vb&#xff0c;vm测试过没问题&#xff0c;vnc没测试不清楚 虚拟机网络&#xff1…

【React】高阶组件

概述 高阶组件并非一个组件&#xff0c;而是增强组件功能的一个函数。 高阶组件的作用是对多个组件公共逻辑进行横向抽离。 高阶组件 – React (reactjs.org) 示例 ChildCom1.jsx import React from react;function ChildCom1(props) {return (<div>这是子组件1<d…

基础算法---滑动窗口

文章目录 什么是滑动窗口1.长度最小的子数组2.无重复字符的最长子串3.最大连续1的个数4.将x减到0的最小操作数5.最小覆盖子串总结 什么是滑动窗口 滑动窗口&#xff08;Sliding Window&#xff09;是一种在计算机科学中用于解决各种子数组或子字符串问题的技术。滑动窗口技术通…

JavaScripts数组里的对象排序的24个方法

1. 使用 Array.prototype.sort() 这是最基本、也是最常用的方法。sort() 方法会原地修改数组&#xff0c;并返回排序后的数组。你需要传入一个比较函数来定义排序逻辑。 const array [{ name: Alice, age: 25 },{ name: Bob, age: 22 },{ name: Charlie, age: 30 } ];// 按照…