useRef 的语法
- 参数为初始值
- 返回一个可变的 ref 对象,该对象只有一个属性 ——
current
const num_obj = useRef(0);
创建了一个 current 属性值为 0 的 ref 对象
{
current:0
}
- current 属性值发生变化,不会触发组件更新渲染(此特征与 useState 不同,useState 声明的变量发生变化,会触发组件更新渲染!)
- 组件更新渲染再次执行
useRef(初始值)
时,不会将 current 属性值恢复为初始值(此特征与 useState 相同!) - 修改current 属性值的语句,一般写在 useEffect 或事件处理函数中
useRef 用于获取 DOM
- useRef 的参数为 null
- 目标DOM的 ref 属性值为 useRef 的返回值
- 只能在目标DOM 在页面完成渲染后,才能获取 DOM
- 目标DOM存在 current 属性里!
import { useRef } from "react";
function Demo() {
const helloDom = useRef(null);
const getHelloDom = () => {
console.log(helloDom.current);
};
return (
<>
<div ref={helloDom}>你好</div>
<button onClick={getHelloDom}>获取DOM</button>
</>
);
}
export default Demo;
useRef 实现自动计数器
import { useEffect, useRef, useState } from "react";
export default function Father() {
const [num, setNum] = useState(0);
const num_obj = useRef(0);
useEffect(() => {
let timer = setInterval(() => {
num_obj.current++;
setNum(num_obj.current);
}, 1000);
return () => clearInterval(timer);
}, []);
return (
<div>
<h1>自动计数器</h1>
<p>num为:{num}</p>
</div>
);
}
- setNum 内不能直接传 num+1,因为依赖项为 [] 的 useEffect 只会在组件挂载时执行一次,在组件更新渲染时不会执行,导致useEffect 内获取到的 num 值永远是 0 ,无法实现预期的持续计数
- 也不能将 useEffect 的依赖项删除,因为删除后,每次组件更新渲染时,都会执行 useEffect 内的代码,导致持续不断地生成计数器,num 的值会越增越快,最后内存溢出!
- 自定义普通的数字变量也能实现,但这种写法打破了纯函数的规则,产生了副作用,不推荐使用
import { useEffect, useState } from "react";
export default function Father() {
const [num, setNum] = useState(0);
let num_temp = 0;
console.log("组件渲染", num_temp); //此处一直打印 0
useEffect(() => {
let timer = setInterval(() => {
console.log("定时器内", num_temp); //此处一直打印增加后的值
num_temp++;
setNum(num_temp + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
return (
<div>
<h1>自动计数器</h1>
<p>num为:{num}</p>
</div>
);
}