React hook 之 useRef

useRef

useRef 是一个 React Hook,它能帮助引用一个不需要渲染的值。

语法

const ref = 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 将返回同一个对象。

用途

使用 ref 引用一个值

在组件顶层调用 useRef 声明一个或多个 ref。

import { useRef } from "react"; function Stopwatch() { const intervalRef = useRef(0); // ... }

useRef 返回一个具有单个 current 属性 的 ref 对象,并初始化为你提供的 初始值。

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

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

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

使用 ref 可以确保:

  1. 可以在重新渲染之间 存储信息(普通对象存储的值每次渲染都会重置)。
  2. 改变它 不会触发重新渲染(状态变量会触发重新渲染)。
  3. 对于组件的每个副本而言,这些信息都是本地的(外部变量则是共享的)。

改变 ref 不会触发重新渲染,所以 ref 不适合用于存储期望显示在屏幕上的信息。如有需要,使用 state 代替。

通过 ref 操作 DOM

使用 ref 操作 DOM 是非常常见的行为。React 内置了对它的支持。

首先,声明一个 初始值 为 null 的 ref 对象

import { useRef } from "react"; function MyComponent() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return <input ref={inputRef} />; }

避免重复创建 ref 的内容

React 会保存 ref 初始值,并在后续的渲染中忽略它。

function Video() { const playerRef = useRef(null); if (playerRef.current === null) { playerRef.current = new VideoPlayer(); } // ... }