hooks使用之useRef
useState
---> 构建组件状态 当状态变更的时候 组件必定重新渲染
useRef
: 构建一个状态出来, 但是这个状态是直接脱离react控制的, 他的变化也不会造成重新渲染, 同时状态还不会因为组件的重新渲染而被初始化
import {useState, useCallback, useRef} from 'react'
export default function Ticker() {
const [timeCount, setTimeCount] = useState(60)
const timerIdRef = useRef(null)
// useRef会返回一个对象 对象里面有个current属性
// ref 是可读可写的
const startTick = useCallback(() => {
if(timerIdRef.current) return
timerIdRef.current = setInterval(() => {
setTimeCount(prev => prev - 1)
}, 1000)
}, [])
const stopTick = useCallback(() => {
if (timerIdRef.current) clearInterval(timerIdRef.current)
}, [])
// 有且只有一个根组件 <></> --> 是一个语法糖 React.Fragment
return (
<>
<button onClick={startTick}>start</button>
<button onClick={stopTick}>stop</button>
<span>{ timeCount }</span>
</>
)
}
处理真实dom
export default function TestInput() {
// 需求 当点击 clickme 的时候 输入框聚焦
const [inputElement, setInputElement] = useState(null)
useEffect(() => {
// 这个真实dom 和react 有没有任何关系
const inputEl = document.getElementsByClassName("input-example")[0]
setInputElement(inputEl)
})
const handlerClick = useCallback(() => {
inputElement.focus()
}, [])
return (
<div>
<input type="text" className="input-example" />
<button onClick={handlerClick}>click me</button>
</div>
)
}
使用useRef
的实现
export default function TestInput() {
const inputElementRef = useRef(null)
// useEffect(() => {
// // 这个真实dom 和react 有没有任何关系
// inputElementRef = document.getElementsByClassName("input-example")[0]
// })
const handlerClick = useCallback(() => {
inputElement.current.focus()
}, [])
return (
<div>
{/* 这种ref 使用了useEffect 去帮你获取dom 并且赋值 */}
<input ref={inputElementRef} type="text" className="input-example" />
{/* */}
{/* <input type="text" className="input-example" /> */}
<button onClick={handlerClick}>click me</button>
</div>
)
}
Question:
既然我可以通过document.xx.getElementById直接拿到真实dom, 那么useRef存在的意义是什么?
- useRef不是不仅为了真实dom服务 构建一个状态出来, 但是这个状态是直接脱离react控制的, 他的变化也不会造成重新渲染, 同时状态还不会因为组件的重新渲染而被初始化
如果不使用useRef去处理真实dom, 会出现什么问题?
- 不用ref就需要构建状态, 而使用状态会造成没必要的重新渲染, 用全局变量去控制, 又会造成闭包问题