React Hook之useRef与createRef

112 阅读4分钟

前言

在看到ahooks库中看到UseMemoizedFn的源码时,发现了使用useRef的身影,然后,就想到之前一般都是使用userRef来来声明一个ref对象,该ref对象一般都是用来操作DOM节点对象的,没想到这个hook的实现还使用到了useRef,于是就有了这篇文章,好奇useRef的作用主要作用是什么?

useRef

官方文档地址:zh-hans.react.dev/reference/r… 建议大家一般遇到什么问题,一定要先看官网,官网其实把所有的用法以及注意事项都标注的很清楚,之前就是没看官方文档,只按照自己理解的当ref来使用。从官方文档给出的信息,我们需要读出:

  • useRef是一个React Hook,它能帮助引用一个不需要渲染的值(直白的理解:就是不需要将值显示在屏幕上的,即屏幕上的值不用随着值变化而更新,可以使用useRef来创建)
  • useRef返回一个可变的ref对象,该对象只有个current属性,初始值为传入的参数
  • 返回的ref对象在组件的整个生命周期内保持不变
  • 当更新current值并不会重新渲染,这是与useState不同的地方
  • 更新useRef是side effect(副作用),所以一般写在useEffect或event handler里
  • 采用useRef,作为组件实例的变量,保证获取到的数据肯定是最新的
  • useRef类似于类组件的this。

使用:

  • useRef(initialValue):在组件顶层调用useRef声明一个ref
import { useRef } from 'react';  
    function MyComponent() {  
    const intervalRef = useRef(0);  
    const inputRef = useRef(null);
    //...
  • initialValue: ref对象的current属性的初始值。可以是任意类型的值.这个参数在首次渲染后被忽略
  • useRef返回一个只有一个属性的对象:即只有属性current,其初始值为传递的initialValue。之后可以将其设置为其他值。如果将ref对象作为一个JSX节点的ref属性传递给React,React将为它设置current属性。在后续的渲染中,useRef将返回同一个对象.
  • 注意:
    1. 可以修改ref.current属性。与state不同,他是可变的。然而,如果它持有一个用于渲染的对象(例如state的一部分)。那么就不应该修改这个对象。
    2. 改变ref.current属性时,React不会重新渲染组件。(因为React不知道它何时会发生改变,因为ref是一个普通的JS对象
    3. 除了初始化外不要再渲染期间写入或者读取ref.current,否则会使组件行为变得不可预测。
    4. 在严格模式下,React 将会 调用两次组件方法。但这只是开发模式下的行为,不会影响生产模式。每个 ref 对象都将会创建两次,但是其中一个版本将被丢弃。如果使用的是组件纯函数(也应当如此),那么这不会影响其行为。

createRef

  • createRef主要用于class组件,而函数组件通常使用useRef;
  • createRef创建一个ref对象,该对象可以包含任意值;

使用

import {createRef,Component} from 'react;'
class MyComponent extends Component {
intervalRef = createRef()
}
  • createRef不接受任何参数
  • 注意事项:
    • createRef总是返回一个不同的对象,这相当于你自己编写了{current:null}
    • 在函数组件中,一般使用useRef,因为它始终返回相同的对象

useRef与createRef的区别

一个组件的正常的生命周期为:创建到挂载组件,更新组件,销毁组件; 在创建到挂载阶段,useRef与createRef没有差别; 更新组件阶段,createRef每次都会返回一个新的引用,而useRef不会随着组件的更新而重新创建 销毁阶段:两者都会销毁

总结

最重要的就是:useRef用于帮助引用一个不需要渲染的值;即在声明之后,后续的渲染中,useRef返回的都是同一个对象,也就是说,改变ref不会触发重新渲染; useRef 返回一个具有单个 current 属性 的 ref 对象,并初始化为你提供的 初始值。

在后续的渲染中,useRef 将返回相同的对象。你可以改变它的 current 属性来存储信息,并在之后读取它。这会让人联想到 state,但是有一个重要的区别。

改变 ref 不会触发重新渲染。这意味着 ref 是存储一些不影响组件视图输出信息的完美选择。例如,如果需要存储一个 interval ID 并在以后检索它,那么可以将它存储在 ref 中。只需要手动改变它的 current 属性 即可修改 ref 的值:

    function handleStartClick() {  
    const intervalId = setInterval(() => {  
    // ...  
    }, 1000);  
    intervalRef.current = intervalId;  
    }
    //在之后,从ref中读物intervalID便可以清除定时器
    function handleStopClick() {  
    const intervalId = intervalRef.current;  
    clearInterval(intervalId);  
    }