详细介绍React中的useRef

714 阅读4分钟

useRef 是React中的一个Hook,用于在组件的整个生命周期中持久存储数据。它主要有两个用途:访问DOM元素和保存跨渲染周期的变量。

1. 访问DOM元素

当你需要直接访问DOM元素或组件实例时,可以使用useRef。通过给useRef赋予初始值null,然后将其返回的对象的.current属性赋给元素的ref属性,React就会将对应的DOM元素赋值给.current

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

function MyComponent() {
  const myInput = useRef(null);

  useEffect(() => {
    // 当组件挂载完成后,`myInput.current`将指向对应的DOM节点
    myInput.current.focus();
  }, []);

  return <input ref={myInput} />;
}

2. 保存跨渲染周期的变量

在组件的多次渲染之间保存数据,而不会触发组件的重新渲染。与组件状态不同,通过useRef保存的值在组件的多次渲染之间是持久的,并且更新ref.current属性不会导致组件重新渲染。

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

function Timer() {
  const intervalId = useRef(null);

  useEffect(() => {
    intervalId.current = setInterval(() => {
      console.log('定时器运行中...');
    }, 1000);
    return () => clearInterval(intervalId.current);
  }, []);

  return <div>查看控制台了解定时器状态。</div>;
}

注意事项

  • useRef返回的对象在组件的生命周期内保持不变,因此可以安全地在任何时候访问.current属性。
  • 更新.current属性不会触发组件重新渲染,这与状态更新(使用useStateuseReducer)形成对比。
  • 使用useRef访问DOM元素通常用于执行焦点管理、文本选择或媒体播放等操作。
  • 当使用useRef保存数据时,应注意避免在渲染期间或副作用函数之外修改.current属性,以防止出现不可预测的行为。

通过useRef,React提供了一种在组件中安全、方便地管理DOM引用和保存数据的方法。

useRef是如何做到在组件的整个生命周期中持久存储数据的?原理是什么

useRef之所以能在组件的整个生命周期中持久存储数据,其原理在于React如何处理Hooks和组件实例的。

原理概述

当React组件首次渲染时,它会创建一个用于该组件的内部状态和上下文的数据结构。这个结构包含了组件所有的state、props以及hooks相关的信息。useRef作为一个Hook,会在这个数据结构中创建一个特定的对象,该对象有一个名为.current的属性。无论组件如何重新渲染,React都会保证访问的是同一个useRef对象,这就是useRef能够跨渲染周期保存数据的原因。

细节解析

  1. 初始化:当组件首次渲染时,useRef(initialValue)会创建一个如{ current: initialValue }的对象。这个对象被保存在React的内部状态中。如果是初次渲染,initialValue就是useRef提供的值。
  2. 组件更新:当组件由于state或props的改变而更新时,React重新执行组件函数。此时,对useRef的调用不会创建一个新的ref对象,而是返回第一次渲染时创建的相同ref对象。因此,.current属性的值在不同渲染间是保持不变的。
  3. 数据持久性:由于useRef返回的ref对象被保存在React的内部状态中,且在组件的连续渲染间保持不变,所以可以在组件的整个生命周期中安全地读取和更新.current属性,而不用担心数据丢失或被重置。
  4. 组件卸载:当组件被卸载时,React清理组件的内部状态,此时useRef创建的ref对象也会被清理。如果组件重新挂载,将会重新初始化一个新的ref对象。

关键点

  • useRef提供的持久性是基于React的渲染和更新机制。React确保每次渲染访问的是相同的ref对象。
  • 更新.current属性不会触发组件重新渲染,因为React不会跟踪.current属性的变化。这与React如何处理state的更新不同,后者会触发组件的重新渲染。
  • useRef与组件实例的生命周期紧密相关,它的数据持久性依赖于组件从挂载到卸载的整个生命周期。

通过这种方式,useRef能够提供一种在组件的整个生命周期中安全、有效地存储和访问数据的手段,适用于管理DOM引用、存储上一次渲染的数据以及其他跨渲染周期的持久数据。