第33节——useRef

2023-09-22 08:00:00

一、概念

useRef,他的作用是“勾住”某些组件挂载完成或重新渲染完成后才拥有的某些对象,并返回该对象的引用。该引用在组件整个生命周期中都固定不变,该引用并不会随着组件重新渲染而失效。返回一个可变的 ref 对象,该对象只有个 current 属性,初始值为传入的参数( initialValue )。返回的 ref 对象在组件的整个生命周期内保持不变。当更新 current 值时并不会 re-render ,这是与 useState 不同的地方。更新 useRef 是 side effect (副作用),所以一般写在 useEffect 或 event handler 里。useRef 类似于类组件的 this

const refContainer = useRef(initialValue);

二、useRef是来解决什么问题的

1、JSX组件转换后对应的真实DOM对象。如何获取input的真实dom

useRef只适合“勾住”小写开头的类似原生标签的组件。如果是自定义的react组件(自定义的组件必须大写字母开头),那么是无法使用useRef(当然也有一些奇淫技巧后面我们后续课程会讲😈)的。比如,我们如何获取这个 真实DOM呢。那么就可以使用useRef

初始化input聚焦
import React,{useEffect,useRef} from 'react'


function Component() {
  //先定义一个inputRef引用变量,用于“勾住”挂载网页后的输入框
  const inputRef = useRef(null);


  useEffect(() => {
    //inputRef.current就是挂载到网页后的那个输入框,一个真实DOM,因此可以调用html中的方法focus()
    inputRef.current.focus();
  },[]);


  return <div>
    {/* 通过 ref 属性将 inputRef与该输入框进行“挂钩” */}
    <input type='text' ref={inputRef} />
  </div>
}
export default Component

2、在useEffect中创建的变量,如何在useEffect 以外的地方,获取并引用

例子

1、组件中有一个变量count,当该组件挂载到网页后,count每秒自动 +1。

2、组件中有一个按钮,点击按钮可以停止count自动+1

import React,{useState,useEffect,useRef} from 'react'


function Component() {
  const [count,setCount] =  useState(0);
  const timerRef = useRef(null);//先定义一个timerRef引用变量,用于“勾住”useEffect中通过setIntervale创建的计时器


  useEffect(() => {
    //将timerRef.current与setIntervale创建的计时器进行“挂钩”
    timerRef.current = setInterval(() => {
      setCount((prevData) => { return prevData +1});
    }, 1000);
    return () => {
      //通过timerRef.current,清除掉计时器
      clearInterval(timerRef.current);
    }
  },[]);


  const clickHandler = () => {
    //通过timerRef.current,清除掉计时器
    clearInterval(timerRef.current);
  };


  return (
    <div>
      {count}
      <button onClick={clickHandler} >stop</button>
    </div>
  )
}


export default Component

4、父组件调用子组件内的方法

注意:除非情况非常特殊,否则一般情况下都不要采用 父组件调用子组件的函数 这种策略

实现思路

父组件中通过 useRef 定义一个钩子变量,例如 childFunRef

父组件通过参数配置,将 childFunRef 传递给子组件

子组件在自己的 useEffect() 中定义一个函数,例如 doSomting()

划重点:一定要在 useEffect() 中定义 doSomting(),不能直接在子组件内部定义。

因为如果 doSomting() 定义在子组件内部,那么就会造成每一次组件刷新都会重新生成一份 doSomthing()

然后将 doSomting() 赋值到 childFunRef.current 中

这样,当父组件想调用子组件中的 doSomting() 时,可执行 childFunRef.current.doSomting()

父组件
import { useRef } from "react";
import ChildComponent from "./child";


const ParentComponent = () => {
  const childFunRef = useRef();
  const handleOnClick = () => {
    if (childFunRef.current) {
      childFunRef.current.doSomething();
    }
  };
  return (
    <div>
      <ChildComponent funRef={childFunRef} />
      <button onClick={handleOnClick}>执行子项的doSomething()</button>
    </div>
  );
};


export default ParentComponent;
子组件
import { useEffect, useState } from "react";


const ChildComponent = ({ funRef }) => {
  const [num, setNum] = useState(0);
  useEffect(() => {
    const doSomething = () => {
      setNum(Math.floor(Math.random() * 100));
    };
    funRef.current = { doSomething }; //在子组件中修改父组件中定义的childFunRef的值
  }, [funRef]);
  return <div>{num}</div>;
};


export default ChildComponent;

三、useRef与createRef的区别

1、useRef是针对函数组件的,如果是类组件则使用React.createRef()。

2、React.createRef()也可以在函数组件中使用。useRef只能在react hooks中使用

3、createRef每次都会返回个新的引用;而useRef不会随着组件的更新而重新创建

更多推荐

Android 混淆使用及其字典混淆(Proguard)

1.使用背景ProGuard能够通过压缩、优化、混淆、预检等操作,检测并删除未使用的类,字段,方法和属性,分析和优化字节码,使用简短无意义的名称来重命名类,字段和方法。从而使代码更小、更高效、更难进行逆向工程。Android代码混淆,又称Android混淆,是一种AndroidAPP保护技术,用于保护APP不被破解和逆

css知识学习系列(2)-每天10个知识点

目录1.基础知识CSS中的伪元素和实际元素有什么区别?2.动画与过渡CSS中的transition和animation有何区别?在什么情况下使用哪种动画?3.Flexbox在Flexbox布局中,“flex-wrap”属性有什么作用?4.Grid请解释CSS中的网格线(gridlines)和轨道(tracks)是什么?

Docker 容器生命周期:创建、启动、暂停与停止

🌷🍁博主猫头虎带您GotoNewWorld.✨🍁🦄博客首页——猫头虎的博客🎐🐳《面试题大全专栏》文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大

Android设计支持库

本文所有的代码均存于https://github.com/MADMAX110/BitsandPizzas设计支持库(DesignSupportLibrary)是Google在2015年的I/O大会上发布的全新MaterialDesign支持库,在这个support库里面主要包含了8个新的MaterialDesign组件

C#里面的三种定时计时器:Timer

在.NET中有三种计时器:1、System.Windows.Forms命名空间下的Timer控件,它直接继承自Componet。Timer控件只有绑定了Tick事件和设置Enabled=True后才会自动计时,停止计时可以用Stop()方法控制,通过Stop()停止之后,如果想重新计时,可以用Start()方法来启动计

什么是Jmeter?Jmeter使用的原理步骤是什么?

1.1什么是JMeterApacheJMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。它可以用于测试静态和动态资源,例如静态文件、Java小服务程序、CGI脚本、Java对象、数据库、FTP服务器,等等。JMeter可以用于对

【Linux】分布式版本控制工具git

​​📝个人主页:@Sherry的成长之路🏠学习社区:Sherry的成长之路(个人社区)📖专栏链接:Linux🎯长路漫漫浩浩,万事皆有期待上一篇博客:【Linux】Linux调试器-gdb文章目录一、前言二、版本控制1、何为版本控制2、版本控制工具①集中式版本控制工具②分布式版本控制工具三、代码托管平台四、Lin

【TAPD】实践:TAPD 项目管理配置

目录一、30人以内团队申请免费企业版(1)首次申请试用期3个月(2)进一步申请免费续期二、成员管理三、用户组管理四、项目管理(1)首个项目配置(2)自定义项目模板(3)二次创建项目五、自定义项目模板好处一、30人以内团队申请免费企业版【Tapd】30人以内团队:申请永久免费的Tapd企业版步骤https://gusan

新款 锐科达 SV-2402VP SIP广播音频模块 支持RTP流音频广播

新款锐科达SV-2402VPSIP广播音频模块支持RTP流音频广播SV-2402VP网络音频模块是一款通用的独立SIP音频功能模块,可以轻松地嵌入到OEM产品中。该模块对来自网络的SIP协议及RTP音频流进行编解码。该模块支持多种网络协议和音频编解码协议,可用于VoIP和IP寻呼以及高质量音乐流媒体播放等应用。同时,S

数字孪生在灌区信息中的应用

灌区信息是智慧水利的组成部分,对灌区现代化改造的支撑作用和地位尤为重要,对促进水利可持续发展有重要意义。灌区信息化系统主要对对灌区的水情、雨情、土壤墒情、气象等信息进行监测,对重点区域进行视频监控,同时对泵站、闸门进行远程控制,实现了信息的测量、统计、分析、控制、调度等功能。为灌区管理部门科学决策提供了依据,提升灌区的

TCP并发服务器的多进程实现与多线程实现

TCP并发服务器的多进程实现与多线程实现一、TCP并发服务器的多进程实现代码#include<my_head.h>#defineSERVER_IP"192.168.125.11"//服务器IP#defineSERVER_PORT6666//服务器端口//子进程处理客户端信息函数intdeal_client_messag

热文推荐