一 介绍
useRef是一个返回可变引用对象的函数,该对象current属性的初始值为传入的initialValue,且返回的对象在组件整个生命周期中持续存在。
1.用法
- 通过ref属性完成对DOM元素的引用
- 通过useRef()实现初始赋值
- 通过current属性查看值
import {useRef} from 'react';
const ref = useRef(initialValue);
···
//可以在组件生命周期的任何时间log该属性以查看其值
console.log(ref.current)
···
return(
<button ref={btnRef}>
点击
</button>
);
2.关于current属性的两个关键点
- 该属性是可变的
- 可以在组件生命周期中随时更改
二 应用
通常情况下,useRef有两种用途:
- 访问DOM节点,或者React元素
- 保持可变变量
1.访问DOM节点,或者React元素
一个简单的案例,通过点击button实现input自动获取焦点
class组件的写法:
import React, {Component, createRef} from "react";
export default class Demo extends Component {
textInput = createRef()
focusTextInput = () => {
if (this.textInput.current) {
this.textInput.current.focus();
}
}
render() {
return (
<>
<input type="text" ref={this.textInput} />
<button onClick={this.focusTextInput}>点击我让input组件获得焦点</button>
</>
);
}
函数式组件的写法:
import React, {useRef} from "react";
export default function Demo() {
const inputRef = useRef(null);
const focusTextInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
}
return (
<>
<input type="text" ref={inputRef} />
<button onClick={focusTextInput}>点击我让input组件获得焦点</button>
</>
);
}
两种写法注意生成ref的方式
2.保持可变变量
在函数组件中,每次re-render就意味着函数重新执行一次,想要在函数内部保持变量引用的话就可以使用useRef。
一个常见的场景就是定时器的清除。我们需要确保setInterval的执行结果timer的引用,才能准确的清除对应的定时器。
import React, { useRef, useEffect } from 'react';
export default function Timer() {
const timerRef = useRef();
useEffect(() => {
timerRef.current = setInterval(() => {
console.log('do something');
}, 1000);
// 组件卸载时,清除定时器
return () => {
timerRef.current && clearInterval(timerRef.current);
}
}, []);
return (
<div>
// ...
</div>
)
}
一定要注意的是,如果一个状态或者数据会影响DOM的渲染结果,一定要避免使用useRef来保持引用。
三 总结一下useRef
当ref对象内容发生变化时,useRef并不会通知你。变更current属性不会引发组件重新渲染。
主要的几种应用场景:
- 使用焦点,模糊,禁用和其他表单管理相关的属性来微管理输入
- 要从元素中添加或删除类,可能控制过渡或者关键帧动画
- 与其他html5库进行交互。这样的库无法通过react状态访问,而Refs为我们提供了一个后备功能。