useRef
2026年3月20日 |
ReactHooks
1. 简介
useRef是React中常用的Hook之一,常用于保存数据、获取dom、引用组件。它和useState一样是可以长期保存值的一个引用容器。它和useState的区别就是它存储的值更改时不会触发组件的渲染。
useState 与 useRef 对比
| 特性 | useState | useRef |
|---|---|---|
| 修改值时 | 触发组件重新渲染 | 不触发渲染 |
| 组件重新渲染时 | 获取的是最新状态值 | 获取的是之前保存的值(.current) |
| 主要用途 | 管理会影响 UI 显示的数据 | 保存 DOM 引用、上一轮值、定时器等 |
| 是否适合作为依赖 | 适合(值变化会触发 effect) | 通常不适合(对象引用不变) |
2. 保存数据
需求:我们现在有一个按钮,当我点击之后清除上一次的定时器,重新开启一个定时器。每次只有一个定时器存在。以下是我们的代码实现:
function App() {
let timer;
const handleClick = () => {
// 本次的timer和上一次的timer不是一个变量
clearInterval(timer);
timer = setInterval(() => {}, 1000);
};
}
以上代码虽然看上去没有问题,但是如果组件重新渲染,是不会清除之前定时器的。当组件重新渲染的时候,会生成一个新的timer,本次的timer和上一个timer不是一个变量。
function App() {
let timer = useRef(null);
const handleClick = () => {
clearInterval(timer.current);
timer = setInterval(() => {}, 1000);
};
}
3. 获取DOM
当我们需要获取dom元素的时候,我们可以使用useRef来保存dom元素的引用。例如:
当我们点击h1元素的时候,会改变h1元素的字体颜色和背景颜色。
4. 引用组件
需求:我们有一个模态框子组件,这个子组件中有显示和隐藏的方法。当父组件想要调用子组件的显示和隐藏方法时,我们可以使用useRef来引用子组件。
父组件:
import { useRef } from "react";
export default function App() {
const modalRef = useRef(null);
return (
<>
<Modal ref={modalRef} />
<button onClick={() => modalRef.current?.showModal()}>显示</button>
</>
);
}
子组件:
import { useImperativeHandle, useState } from "react";
export function Modal(props, ref) {
// 配置组件的ref,使父组件可以调用子组件的方法
// 这里我们只暴露了showModal方法,其他方法可以不暴露
useImperativeHandle(ref, () => ({
showModal: showModal,
}));
const [show, setShow] = useState(false);
const showModal = () => {
setShow(true);
};
const hideModal = () => {
setShow(false);
};
return <h2>模态框</h2>;
}
这样父组件就可以调用子组件的showModal方法了。