看一下官网定义
useRef是一个React Hook,它能帮助引用一个不需要渲染的值
这句话透露出一个信息,不需要渲染的值可以用useRef引用,那需要渲染的值用什么引用呢?当然是useState了,需要渲染的值指的就是状态嘛!
看下官网的例子,可以方便你理解:
import React,{useState, useEffect, useRef} from 'react';const DemoRef = () => {const [count, setCount] = useState(0)let timer = null;useEffect(() => {timer = setInterval(()=>{//这里注意一下不要直接传递下一个状态setCount(count+1),这样做的话,你会发现一直是0-->1来回闪烁,//这是因为set函数不会更新已经运行在代码中的count状态变量,而传递一个更新函数setCount(count=>count+1)//则会获取待定状态,并从中计算下一个状态setCount(count=>count+1)},1000)}, [])const onClick = () => {console.log(timer,'timer')clearInterval(timer)}return (<div><p>count:{count}</p><button onClick={onClick}>点击清除</button></div>)
}
export default DemoRef;
结果如图,会发现timer一直是null,这是因为每次setState之后,组件都会重新运行一遍,然后let timer = null;每次都每次都会重新赋值为null。这样很明显,内存泄漏。
这时就可以使用useRef来处理这个了
import React,{useState, useEffect, useRef} from 'react';const DemoRef = () => {const [count, setCount] = useState(0)let timer = useRef();useEffect(() => {timer.current = setInterval(()=>{//这里注意一下不要直接传递下一个状态setCount(count+1),这样做的话,你会发现一直是0-->1来回闪烁,//这是因为set函数不会更新已经运行在代码中的count状态变量,而传递一个更新函数setCount(count=>count+1)//则会获取待定状态,并从中计算下一个状态setCount(count=>count+1)},1000)}, [])const onClick = () => {console.log(timer,'timer')clearInterval(timer.current)}return (<div><p>count:{count}</p><button onClick={onClick}>点击清除</button></div>)
}
export default DemoRef;
通过这个例子就能看出useRef的一个功能,那就是引用一个值,使其跳过组件的重新渲染过程。
useRef还有一个功能,那就是操作Dom。看下面这个例子
import React,{useRef} from 'react';const RefDom = () => {const inputRef = useRef();const onClick = () => {console.log(inputRef.current)inputRef.current.value = 'lili'}return (<div><input type="text" ref={inputRef}/><button onClick={onClick}>点击自动填充</button></div>)
}
export default RefDom;
可以看到,点击按钮之后,会给input填充lili
使用 ref 可以确保:
- 可以在重新渲染之间 存储信息(普通对象存储的值每次渲染都会重置)。
- 改变它 不会触发重新渲染(状态变量会触发重新渲染)。
- 对于组件的每个副本而言,这些信息都是本地的(外部变量则是共享的)。
改变 ref 不会触发重新渲染,所以 ref 不适合用于存储期望显示在屏幕上的信息。如有需要,使用 state 代替。