应用场景
获取组件的实例,例如父组件需要调用子组件的方法时。 获取DOM对象,即用于绑定某些DOM,监听组件的事件 当成函数组件中的全局变量,跨渲染周期保存数据,即组件被多次渲染之后依旧不变的属性,state不能存储跨渲染周期的数据,因为state一旦修改了它,就会造成组件的重新渲染,而useRef不会重新引起渲染。
特性
- useRef返回一个可变的ref对象,其.currentn履性被初始化为传入参数(initalValue)。返回的ref对象在组件的生命周期内保持不变。
- curent值的改变不会引起组件重新渲染,相当于组件的全局变量。
- ref和render保持着一种引用关系,即地址的引用,它拿到结果一定也是最新的状态。
语法
const refContainer = useRef(initialValue);
用法示例
(1)获取DOM
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
(2)父组件调用子组件方法
// props子组件中需要接受ref
let ChildComp = (props,ref) => {
// 此处注意useImperativeHandle方法的的第一个参数是目标元素的ref引用
useImperativeHandle(ref, () => ({
// changeVal 就是暴露给父组件的方法
changeVal: (newVal) => {
}
}));
return (
<div>{val}</div>
)
}
ChildComp = forwardRef(ChildComp)
/* FComp 父组件 */
import {useRef} from 'react';
const FComp = () => {
const childRef = useRef();
const updateChildState = () => {
// changeVal就是子组件暴露给父组件的方法
childRef.current.changeVal(99);
}
return (
<>
<ChildComp ref={childRef} />
<button onClick={updateChildState}>触发子组件方法</button>
</>
)
}
(3)组件全局变量用
function App() {
const [count, setCount] = useState(0);
// 把定时器设置成全局变量使用useRef挂载到current上
const timer = useRef();
// 首次加载useEffect方法执行一次设置定时器
useEffect(() => {
timer.current = setInterval(() => {
setCount(count => count + 1);
}, 1000);
}, []);
// count每次更新都会执行这个副作用,当count > 5时,清除定时器
useEffect(() => {
if (count > 5) {
clearInterval(timer.current);
}
});
return <h1>count: {count}</h1>;
}