用途
1. 声明变量
希望组件“记住”某些信息,但又不想让这些信息 触发新的渲染 时 (能够跨渲染周期保存值)
import { useRef } from 'react';
const ref = useRef(0);
// useRef 返回一个这样的对象:
// {
// current: 0 // 你向 useRef 传入的值
// }
// 使用:
ref.current = 12.操作 DOM
import { useRef } from 'react';
const myRef = useRef(null);
return (
<div ref={myRef}></div>
)
// 使用:
myRef.current.focus()Warning
不能在渲染期间直接使用 ref 进行操作(即不能直接写在组件内最外层中的逻辑代码中,一般写在事件或函数中),因为此时 DOM 节点尚未创建
如下面的写法是错误的:
function VideoPlayer({ src, isPlaying }) {
const ref = useRef(null);
if (isPlaying) {
ref.current.play(); // 渲染期间不能调用 `play()`。
} else {
ref.current.pause(); // 同样,调用 `pause()` 也不行。
}
return <video ref={ref} src={src} loop playsInline />;
}动态 ref
因为 Hook 只能在组件的顶层被调用,所以 ref 的数量需要是预先确定的。但有时候,可能需要为列表中的每一项都绑定 ref ,而又不知道会有多少项
解决方法:
将函数传递给 ref 属性
<div ref={(node) => {
console.log('Attached', node);
return () => {
console.log('Clean up', node)
}
}}>- 当
<div>DOM 节点被添加到屏幕上时,React 将使用该节点作为参数调用 ref 回调函数。 - 当这个
<div>DOM 节点被移除的时候, React 将调用回调返回的清理函数。
在上面的示例中,(node) => { ... } 在每次渲染时都是一个不同的新函数。当组件重新渲染时,先前的函数将被调用并传递 null 作为参数,并且下一个新函数将被调用并传递对应 DOM 节点作为参数。