【React】ref

news2025/2/24 21:10:25

概述

使用 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 = 0
    if (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.coloradmin.cn/o/1854573.html

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

相关文章

一、系统学习微服务遇到的问题集合

1、启动了nacos服务&#xff0c;没有在注册列表 应该是版本问题 Alibaba-nacos版本 nacos-文档 Spring Cloud Alibaba-中文 Spring-Cloud-Alibaba-英文 Spring-Cloud-Gateway 写的很好的一篇文章 在Spring initial上面配置 start.aliyun.com 重新下载 < 2、 No Feign…

美团携手HarmonyOS SDK,开启便捷生活新篇章

华为开发者大会&#xff08;HDC 2024&#xff09;于6月21日在东莞松山湖拉开序幕&#xff0c;通过一系列精彩纷呈的主题演讲、峰会、专题论坛和互动体验&#xff0c;为开发者们带来了一场知识与技术的盛宴。6月23日&#xff0c;《HarmonyOS开放能力&#xff0c;使能应用原生易用…

上位机图像处理和嵌入式模块部署(mcu和swd接口)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 最近学习mcu的时候&#xff0c;接触了不少调试器&#xff0c;这里面有daplink、st-link v2、j-link v9。虽然模块的形状可能不太一样&#xff0c;但…

程序人生:关于RHCE红帽认证这件事

花了两个月备考红帽&#xff0c;最终终于双满分通过。 关于考试 RHCE红帽认证总共需要考两门&#xff1a;RHCSA、RHCE。 RHCSA主要是考察基本的Linux操作&#xff1a;用户、权限、空间扩容、yum、容器等内容。 RHCE主要是考察ansible playbook 代码的开发。 通过考试没有别…

【web1】标签,css,js

文章目录 1.标签&#xff1a;input1.1 html&#xff1a;HTML&#xff08;用于创建网页结构&#xff09;&#xff0c;CSS&#xff08;对页面进行美化&#xff09;&#xff0c;JavaScript&#xff08;用于与用户交互&#xff09;1.2 文本标签&#xff1a;字体属性1.3 a标签&#…

DIVE INTO DEEP LEARNING 50-55

文章目录 50. semantic segmentation50.1 Basic concepts50.2 Major application 51. Transposed convolution51.1 Basic concepts51.2 Major role51.3 Implementation steps and application areas51.4 Transposed convolution51.5 Transposed convolution is a type of convo…

卧槽,6。套死你猴子,Tomcat访问html页面显示源码?

卧槽&#xff0c;6。Tomcat访问html页面显示源码&#xff1f; 元凶text/explain //踩坑&#xff01;&#xff01;&#xff01;不能用 servletResponse.setContentType("text/explain&#xff0c;否则访问html会看到源码&#xff0c;而不是渲染页面; charsetUTF-8"…

IDEA各种实体类运行爆红,不运行就没事

1.问题描述 如图所示&#xff0c;后端项目的import的各种entity爆红&#xff0c;点击也有导入包的提示&#xff0c;且这种报红几乎遍布了整个工程项目 2.我的解决方案 清空缓存&#xff0c;然后把target文件删掉&#xff0c;重新跑 3.小结 idea项目有时候就是一个核弹&…

【科普】半导体制造过程的步骤、技术、流程

在这篇文章中&#xff0c;我们将学习基本的半导体制造过程。为了将晶圆转化为半导体芯片&#xff0c;它需要经历一系列复杂的制造过程&#xff0c;包括氧化、光刻、刻蚀、沉积、离子注入、金属布线、电气检测和封装等。 基本的半导体制造过程 1.晶圆&#xff08;Wafer&#xf…

免费一年SSL证书申请——建议收藏

免费一年SSL证书申请——建议收藏 获取免费一年期SSL证书其实挺简单的 准备你的网站&#xff1a; 确保你的网站已经有了域名&#xff0c;而且这个域名已经指向你的服务器。还要检查你的服务器支持HTTPS&#xff0c;也就是443端口要打开&#xff0c;这是HTTPS默认用的。 验证域…

23.并发

目录 一、一些概念二、进程和线程2.1 概念2.2 多线程导致的问题2.3 使用spawn创建新线程2.4 线程与move闭包 三、消息传递3.1 概念3.2 创建通道3.3 示例3.4 其它测试 四、共享状态并发4.1 互斥器4.2 Mutex的API4.3 多线程共享Mutex1&#xff09;在多线程之间共享值&#xff1b;…

ARC学习(3)基本编程模型认识(三)

笔者来介绍arc的编程模型的中断流程和异常流程 1、中断介绍 主要介绍一下中断进入的流程&#xff0c;包括需要配置的寄存器等信息。 中断号&#xff1a;16-255&#xff0c;总共240个中断。触发类型&#xff1a;脉冲或者电平触发中断优先级&#xff1a;16个&#xff0c;0最大&…

在linux系统中使用docker、mysql实例

systemctl 是一个命令行工具&#xff0c;用于控制和管理基于 systemd 的 Linux 发行版中的系统和服务。 启动服务 &#xff1a;使用 systemctl start [service-name] 开始一个服务。 如启动docker&#xff1a;systemctl start docker 停止服务 &#xff1a;使用 systemctl st…

【python】python葡萄酒国家分布情况数据分析pyecharts可视化(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

力扣SQL50 超过5名学生的课

Problem: 596. 超过5名学生的课 Code select class from courses group by class having count(distinct student) > 5;

FFmpeg源码:ff_ctz / ff_ctz_c函数分析

一、ff_ctz函数的作用 ff_ctz定义在FFmpeg源码目录的libavutil/intmath.h 下&#xff1a; #ifndef ff_ctz #define ff_ctz ff_ctz_c /*** Trailing zero bit count.** param v input value. If v is 0, the result is undefined.* return the number of trailing 0-bits*/…

如何使用AI工具进行写作

随着AI人工智能技术的飞速发展&#xff0c;AI工具已经逐渐成为学术和专业写作的得力助手。AI工具不仅可以帮助我们提高写作效率&#xff0c;还能在内容创作上提供灵感和支持。在本文中&#xff0c;小编将和大家分享如何利用AI工具提高写作效率和质量&#xff0c;并确保文章的原…

基于CDMA的多用户水下无线光通信(3)——解相关多用户检测

继续上一篇博文&#xff0c;本文将介绍基于解相关的多用户检测算法。解相关检测器的优点是因不需要估计各个用户的接收信号幅值而具有抗远近效应的能力。常规的解相关检测器有运算量大和实时性差的缺点&#xff0c;本文针对异步CDMA的MAI主要来自干扰用户的相邻三个比特周期的特…

活用变量,让Postman的使用飞起来

在 Postman 中使用变量是一种非常强大的功能&#xff0c;它可以极大地增强 API 测试和开发的灵活性和效率。 Postman变量的类型 变量在 Postman 中可以在多个层次设置和使用&#xff0c;包括 全局变量环境变量集合变量局部变量&#xff08;如在脚本中暂时创建的变量&#xf…

使用MyBatis Generator自动代码生成器简化Java持久层开发

在Web开发中&#xff0c;数据访问层&#xff08;DAO层&#xff09;的编码工作往往重复且繁琐&#xff0c;尤其是在处理数据库表与Java对象之间的映射时。MyBatis Generator是一款强大的代码生成工具&#xff0c;它能自动生成DAO接口、Mapper XML文件和实体类&#xff0c;极大地…