前言
本章解锁useRef 源码,useRef 的源码还是很简单的,也是使用十分广泛的hook,而且使用场景还是很广泛的;
useRef 也会配合useImperativeHandle 和forwardRef 使用;
useRef并不会导致重新渲染,通常会做一些缓存相关的问题。
源码解析
js
const ref = useRef(initialValue)
按照常规流程,调用HooksDispatcherOnMountInDEV.useRef 的方法,前置check检查方法,核心方法mountRef ;
调用mountWorkInProgressHook方法,
js
const hook = {
memoizedState: null,
baseState: null,
baseQueue: null,
queue: null,
next: null
};
fiber.memoizedState = hook;
mountRef的核心代码也很简单
js
const ref = {current: initialValue};
hook.memoizedState = ref;
返回ref对象,源码还是很简单,因为ref是一个对象,默认是使用current对象,可以把useRef当成一个可以缓存的对象;
直接修改ref对象值,并不会导致组件重新渲染,需要通过其他的方法触发渲染。
update阶段
调用HooksDispatcherOnUpdateInDEV.useEffect 方法,调用check方法,核心方法updateRef
调用updateWorkInProgressHook 方法,将mount阶段创建的hook,copy一份,返回fiber.memoizedState ;
因为copy的时候会把上一次的值保存下来,并且是对象引用,所以每次都是最新值。
总结
useRef
就是简单创建hook对象,创建一个ref对象。
补充
在使方法通常是
js
const ref = useRef(null);
ref.current = value;
可以直接通过改变值的方式修改;
js
const ref = useRef(null);
<div ref={ref}></div>
第二种方式涉及到react dom解析,理解成ref.current = div ;
第一种方式常常使用方式,因为ref是一个对象,也可以按照对象方式使用,
js
const ref = useRef(null);
ref.key = 'value';
console.log(ref.key)
不常用,不推荐,但是可以使用。