1、访问 DOM 节点
import { useRef } from 'react'
export default () => {
const inputElement = useRef(null)
const handleClick = () => {
inputElement.current.focus()
}
return {
<>
<input ref={inputElement} type="text" />
<button onClick={handleClick}>foucs input</button>
</>
}
}
2、useRef 用来跨越渲染周期存储数据,而且对它修改也不会引起组件渲染
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组建的整个生命周期内保持不变。
import React, { useState, useRef } from 'react'
export default () => {
const [period, setPeriod] = useState(selectedPeriod)
const [subject, setSubject] = useState(selectedSubject)
const [periodList, setPeriodList] = useState([])
const [subjectList, setSubjectList] = useState([])
// 缓存科目
const subjectRef = useRef(subject)
useEffect(() => { subjectRef.current = subject }, [subject])
useEffect(() => {
setPeriod(selectedPeriod)
setSubject(selectedSubject)
}, [selectedPeriod, selectedSubject])
// 学段列表
useEffect(() => {
(async () => {
const periodList = await onGetPeriodList()
setPeriodList(periodList)
})()
}, [onGetPeriodList])
// 切换学段要重新获取对应的科目
useEffect(() => {
(async () => {
const subjectList = await onGetSubjectList(period)
setSubjectList(subjectList)
// 这里用 useRef 缓存切换学段前选中的科目,在改变后,如果有相同的科目,就默认选中,否则选中第一个
// 这里不能直接使用 subject 的原因是:使用 subject,就要添加 subject 作为依赖,在调用setSubject 的时候会导致死循环
const { current: subjectCache } = subjectRef
const defaultSubject = subjectList.find((subject) => subject.id === subjectCache.id) || subjectList[0]
setSubject(defaultSubject)
})()
}, [period, onGetSubjectList])
}
3、useRef 和 createRef 的区别
reateRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。
import React, { useState, useRef } from 'react'
export default () => {
const [renderIndex, setRenderIndex] = useState(1)
const useRefDom = useRef()
const createRefDom = createRef()
if (!useRefDom.current) {
useRefFDom.current = renderIndex
}
if (!createRefDom.current) {
createRefDom.current = renderIndex
}
return (
<>
<p>current render index: { renderIndex }</p>
<p>useRefDom: {useRefDom.current}</p>
<p>createRefDom: {createRefDom.current}</p>
<button onClick={setRenderIndex(prev => prev + 1)}>
cause re-render
</button>
</>
)
}
4、小结
- useRef 是一个方法,且 useRef 返回一个可变的ref对象(对象!!!);
- initialValue 被赋值给其返回值的 .current 对象;
- ref 对象与自建一个 { current:'' } 对象的区别是:useRef 会在每次渲染时返回同一个 ref 对象,即返回的 ref 对象在组件的整个生命周期内保持不变。自建对象每次渲染时都建立一个新的。
- ref 对象的值发生改变之后,不会触发组件重新渲染。
- 本质上,useRef 就是一个其 .current 属性保存着一个可变值“盒子”,类似于 this,dom、对象等任何可变值