useRef
是 React Hooks 中的一个钩子,用于在函数组件中创建和获取对 DOM 或 React 元素的引用。useRef
返回一个可变的对象,该对象的 current
属性被初始化为传入的参数(通常为 null
),并在组件的整个生命周期中保持不变。
主要用途有两个:
-
获取 DOM 元素的引用:可以使用
useRef
获取渲染后的 DOM 元素的引用,从而进行操作或获取其属性。 -
在渲染之间保持可变的值:
useRef
的current
属性可以在渲染之间保持值,而不触发组件重新渲染。
以下是一些示例用法:
1. 获取 DOM 元素的引用
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const myRef = useRef(null);
useEffect(() => {
// 在组件挂载后,通过 myRef.current 获取到 DOM 元素
console.log(myRef.current); // 输出渲染后的 DOM 元素
}, []);
return <div ref={myRef}>This is my component</div>;
}
2. 保持可变的值
import React, { useRef, useEffect } from 'react';
function TimerComponent() {
const secondsElapsed = useRef(0);
useEffect(() => {
const intervalId = setInterval(() => {
secondsElapsed.current += 1;
console.log(`Seconds elapsed: ${secondsElapsed.current}`);
}, 1000);
// 组件卸载时清除定时器
return () => clearInterval(intervalId);
}, []);
return <div>Timer Component</div>;
}
在上述示例中,secondsElapsed
是一个 useRef
,它的 current
属性在渲染之间保持可变的值,而不触发组件重新渲染。这使得定时器中的逻辑能够在多次渲染之间共享和保持状态。
总之,useRef
是一个强大的工具,既可以用于获取 DOM 元素的引用,也可以用于在渲染之间保持可变的值。
在使用 useRef
时,有一些陷阱和注意事项需要注意,以确保正确的使用和避免潜在的问题:
-
不会触发重新渲染:
useRef
创建的引用对象在组件重新渲染时不会发生变化,因此修改useRef
的current
属性不会导致组件重新渲染。如果你希望引起重新渲染,应该使用useState
。 -
异步更新: 更新
useRef
的current
属性是异步的,这意味着如果你在同一个函数中多次修改current
,React 不会保证每次修改都立即生效。如果你需要获取更新后的值,通常在下一次渲染时生效。
const myRef = useRef(0);
const updateRef = () => {
myRef.current = myRef.current + 1;
console.log(myRef.current); // 不一定是更新后的值
};
// 在这里访问 myRef.current 可能不是最新的值
-
不要在渲染期间写入或者读取 ref.current:
React 期望组件主体 表现得像一个纯函数:
在 渲染期间 读取或写入 ref 会破坏这些预期行为。
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);
}
// ...
}
-
不要在
useEffect
依赖中使用: 不要将useRef
放入useEffect
依赖数组中,因为useEffect
会在每次渲染时都创建新的引用。如果需要在useEffect
中访问最新的useRef
值,可以在useEffect
内部直接使用ref.current
。
function MyComponent() {
// ...
useEffect(() => {
// ✅ 可以在 Effect 中读取和写入 ref
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ 可以在事件处理程序中读取和写入 ref
doSomething(myOtherRef.current);
}
// ...
}
网友评论