在组件顶层调用 useRef 以声明一个 ref
const ref = useRef(initialValue)
console.log(ref.current)
initialValue:ref 对象的 current 属性的初始值。可以是任意类型的值。这个参数在首次渲染后被忽略。
current 返回一个只有一个属性的对象, 初始值为传递的 initialValue。
可以修改 ref.current 属性。与 state 不同,它是可变的。然而,如果它持有一个用于渲染的对象(例如 state 的一部分),那么就不应该修改这个对象。
改变 ref.current 属性时,React 不会重新渲染组件。
useRef 可以保存 DOM 节点的引用
import { useRef } from 'react';
function MyComponent() {
const inputRef = useRef(null);
// ...
return <input ref={inputRef} />;
function handleClick() {
inputRef.current.focus();
}
useRef 也可以保存任何可变的数据,而不用触发组件的重新渲染
// 可以记录定时器id实现防抖
function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}
useRef 也可以访问子组件的实例
父组件
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const childRef = useRef();
const handleClick = () => {
childRef.current.focusInput();
};
return (
<div>
<ChildComponent ref={childRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
export default ParentComponent;
子组件
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
const ChildComponent = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focusInput() {
inputRef.current.focus();
}
}));
return <input ref={inputRef} type="text" />;
});
export default ChildComponent;
useRef 也可以useRef 来保存上一次的值,供下次渲染时进行比较或其他操作
不要在渲染期间写入或者读取 ref.current。
function MyComponent() {
// ...
// ???? 不要在渲染期间写入 ref
myRef.current = 123;
// ...
// ???? 不要在渲染期间读取 ref
return <h1>{myOtherRef.current}</h1>;
}
可以在 事件处理程序或者 Effect 中读取和写入 ref。
function MyComponent() {
// ...
useEffect(() => {
// ✅ 可以在 Effect 中读取和写入 ref
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ 可以在事件处理程序中读取和写入 ref
doSomething(myOtherRef.current);
}
// ...
}
如果不得不在渲染期间读取 或者写入,那么应该 使用 state 代替。
避免重复创建 ref 的内容
function Video() {
const playerRef = useRef(new VideoPlayer());
// ...
虽然 new VideoPlayer() 的结果只会在首次渲染时使用,但是依然在每次渲染时都在调用这个方法。如果是创建昂贵的对象,这可能是一种浪费。
为了解决这个问题,你可以像这样初始化 ref:
function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...