乐趣区

关于react.js:react-hooks本质探索-useRef源码详解

先要晓得几点前提要点

  1. 在 functional component 中,每一次 props 的变动、执行 setState 操作都会导致组件办法从新执行。
  2. 基于 1,组件办法执行后,所有的间接定义的 const、let 变量都会从新定义。
  3. 所以对于不须要变动的常量,个别用 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 函数

退出移动版