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 可以确保:
- 可以在重新渲染之间 存储信息(普通对象存储的值每次渲染都会重置)。
- 改变它 不会触发重新渲染(状态变量会触发重新渲染)。
- 对于组件的每个副本而言,这些信息都是本地的(外部变量则是共享的)。
改变 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(); } // ... }