先要晓得几点前提要点
- 在 functional component 中,每一次 props 的变动、执行 setState 操作都会导致组件办法从新执行。
- 基于 1,组件办法执行后,所有的间接定义的 const、let 变量都会从新定义。
- 所以对于不须要变动的常量,个别用 useRef 封装起来。
常见的应用办法:
const a = useRef(initalValue);
在执行组件办法的时候,a 不会被从新赋值。那么 useRef 在这里实质上干了什么呢?
useRef 实质上是 ReactCurrentDispatcher.current 上的一个办法,这个办法接管一个初始值,返回一个对象,这个对象中只有一个 current 属性。
在执行组件办法的时候,这个 current 的值不会被重置,也就是说,每一次执行组件办法,用到的都是同一个值。
当然这里有一个问题,返回的这个对象为什么不会被重置?
应该是 react 用了一种时序的保留办法,在初始化时,将值记录在一个对象中;反复执行组件办法的时候,再从这个对象中取出来赋值到了 a 上。
上面看源码片段,这是初始化 ref 的源码:
useRef: function (initialValue) {
currentHookNameInDev = 'useRef';
mountHookTypesDev();
return mountRef(initialValue);
},
function mountRef(initialValue) {var hook = mountWorkInProgressHook();
var ref = {current: initialValue};
{Object.seal(ref);
}
hook.memoizedState = ref;
return ref;
}
附:Object.seal 只是让 ref 里的 key 无奈删除,value 能够扭转。
上面是更新 ref(第二次当前执行组件办法)的代码片段:
useRef: function (initialValue) {
currentHookNameInDev = 'useRef';
updateHookTypesDev();
return updateRef(); // 能够留神到这里是 update},
这里 mountHookTypesDev 和 updateHookTypesDev 不重要。次要逻辑是 mountRef 和 updateRef 办法。
能够看到,updateRef 其实就是返回了 hook 里记录的 memoizedState
至于 mountWorkInProgressHook 和 updateWorkInProgressHook,是两个比较复杂的办法。波及到 hook 的实质,实际上 useState 也是用这个形式存储值的。
详见另一篇文章:react hooks 源码外围:workInProgressHook 函数