认识
一、认识
函数组件创建Ref
,可以用 hooks
中的 useRef
来达到同样的效果
二、语法
export default function Index(){
const currentDom = React.useRef(null)
React.useEffect(()=>{
console.log( currentDom.current ) // div
},[])
return <div ref={ currentDom } >ref对象模式获取元素或组件</div>
}
三、类型注解
3.1 元素
const divRef: RefObject<HTMLDivAreaElement> = useRef(null);
const inputRef: RefObject<HTMLInputAreaElement> = useRef(null);
3.2 对象
const objectRef: RefObject<ObjectType> = useRef(null);
四、总结沉淀
4.1 useRef 实现原理?
useRef
用于在函数组件中存储数据, 可以随意更新 ref.current.xx
的值, 并且进行同步更新, 但是 useRef
的更新不会触发组件渲染。
Mount
阶段: 调用 mountRef
, 创建一个 Hook
对象, 存储在 当前处理的 fiber.memoizedState
中。Hook
对象中也有一个 memoizedState
, 用于存储 { current: xx }
。存储完成后, 返回 { current: xx }
Update
阶段: 从当前的 Fiber
中取出 Hook
链表, 依次循环遍历执行, 执行到 useRef
链时, 执行 updateRef
, 直接返回 Hook.memoizedState
就好了。
4.2 React 中 refs 是干嘛用的?
在 React
中, refs
主要用于获取对 DOM
元素或 React
实例的直接引用,从而可以进行一些非声明式的操作。具体来说,refs
的用途包括:
-
访问
DOM
节点: 当需要直接操作底层DOM
(例如,设置焦点、测量尺寸、触发动画或滚动位置)时,可以使用refs
获取对应的DOM
元素引用。 与第三方库集成 -
访问子组件实例:
ref
可以结合forward
, 子组件通过useImperativeHandle
自定义由ref
暴露出来的句柄, 供父组件使用。 -
存储不需要引起渲染的数据: 在函数组件中, 还可以用于存储任何不需要引起重新渲染的可变数据(例如,存放定时器
ID
、缓存值等)。 避免不必要的渲染
4.3 useState 与 useRef 有什么区别?
useRef
存储、返回的结构为 { current: xx }
, 更新是同步的, 更新 ref.current
不会触发组件重新渲染。
useSate
: 存储状态值, 返回的结构为 [状态值, 更新状态函数]
, 返回的第二个元素为 dispatchAction
, 封装了调度更新的逻辑, 里面的主要逻辑为: 确定该更新所属的优先级(即 Lane
), 并生成一个 Update
对象, 其中包含了此次更新的 action
(可能是新状态值或用于计算状态的函数), 基于 eagerState
策略, 通过 Object.is
比较最新结果与之前结果, 如果状态发生变化, 将该 Update
插入到对应 Hook
的更新队列 Hook.UpdateQueue
中, 调用 scheduleUpdateOnFiber
,标记当前 Fiber
需要更新,并由调度器安排后续渲染任务。useState
更新是异步的, 并且会合并多次更新, React
会在合适的时候重新渲染组件。