切换主题
Ref Hook
字数
462 字
阅读时间
3 分钟
useRef
允许组件保存一些不用于渲染的信息:
- 希望组件"记住"某些信息,但又不想让这些信息触发新的渲染
useRef 使用场景
- 存储 DOM 元素引用
tsx
function VideoPlayer() {
const videoRef = useRef(null)
const play = () => {
videoRef.current.play()
}
const pause = () => {
videoRef.current.pause()
}
return (
<div>
<video ref={videoRef}>
<source src="video.mp4" type="video/mp4" />
</video>
<button onClick={play}>播放</button>
<button onClick={pause}>暂停</button>
</div>
)
}
- 保存定时器 ID
tsx
function AutoSave({ onSave }) {
const saveTimerRef = useRef(null)
useEffect(() => {
// 每 5 秒自动保存
saveTimerRef.current = setInterval(() => {
onSave()
}, 5000)
return () => {
// 清理定时器
clearInterval(saveTimerRef.current)
}
}, [onSave])
return <div>自动保存中...</div>
}
- 记录前一次的值
tsx
function MessageList() {
const [messages, setMessages] = useState([])
const prevMessagesRef = useRef([])
useEffect(() => {
// 保存前一次的消息列表
prevMessagesRef.current = messages
}, [messages])
const hasNewMessages = messages.length > prevMessagesRef.current.length
return (
<div>
{hasNewMessages && <div>有新消息!</div>}
{/* 消息列表渲染 */}
</div>
)
}
- 存储可变值(不触发重渲染)
tsx
function StopWatch() {
const [time, setTime] = useState(0)
const intervalRef = useRef(null)
const isRunningRef = useRef(false) // 不需要触发重渲染的状态
const start = () => {
if (isRunningRef.current) return
isRunningRef.current = true
intervalRef.current = setInterval(() => {
setTime(t => t + 1)
}, 1000)
}
const stop = () => {
isRunningRef.current = false
clearInterval(intervalRef.current)
}
return (
<div>
<div>时间: {time}秒</div>
<button onClick={start}>开始</button>
<button onClick={stop}>停止</button>
</div>
)
}
useRef 特点
- ref.current 的变化不会触发组件重新渲染
- ref 值在组件的整个生命周期内保持不变
- 适合存储那些不需要参与 UI 渲染的值
- 常用于存储 DOM 引用、定时器 ID、前一次的值等
使用建议
- 如果值需要参与渲染,使用 useState
- 如果值仅用于存储/记忆且不需要触发重渲染,使用 useRef
- 不要在渲染期间读取或写入 ref.current