这次来看useCallback。useCallback是所有原生use中比较简单的函数

其实整体跟useRef/useState相似。

咱们间接看源码。

初始化的时候,次要执行如下代码:

function mountCallback(callback, deps) {  // 获取以后钩子,也就是链表指针  var hook = mountWorkInProgressHook();    // deps是useCallback的第二个参数,也就是什么状况下须要更新callback  var nextDeps = deps === undefined ? null : deps;    // 两个值存到hook.memoizedState,也是hooks这套代码的常见伎俩  hook.memoizedState = [callback, nextDeps];    // 返回callback。就是传入什么,返回什么。  return callback;}

要害是第二次渲染functional component时做的事件:

function updateCallback(callback, deps) {  // 通用做法。    var hook = updateWorkInProgressHook();    // 获取以后的依赖值,是一个数组  var nextDeps = deps === undefined ? null : deps;    // 获取之前的依赖值,用于比照的。也是一个数组,这个数组中[1]的值才是依赖值  var prevState = hook.memoizedState;  // 检测确定prevState存在。什么状况不存在?临时不晓得  if (prevState !== null) {    //  检测nextDeps存在。这一行和上一行的判断是能够合并的。    if (nextDeps !== null) {      // 后面说道,prevState上[1]的值才是之前的依赖值。      var prevDeps = prevState[1];            // 判断以后的依赖的值和之前依赖的值是否相等      if (areHookInputsEqual(nextDeps, prevDeps)) {        // prevState[0]就是之前的那个callback,阐明函数没变,还是那个          return prevState[0];      }    }  }  // 这里是prevState不存在,或者nextDeps(以后值)和prevDeps(前值)不同  // 或者nextDeps不存在(等于是变动了,也就是说,如果第二个参数传入null,每次都会从新定义函数)  hook.memoizedState = [callback, nextDeps];  // 返回新函数  return callback;}

附上areHookInputsEqual的源码:

function areHookInputsEqual(nextDeps, prevDeps) {  {    if (ignorePreviousDependencies) {      // Only true when this component is being hot reloaded.      return false;    }  }  if (prevDeps === null) {    {      error('%s received a final argument during this render, but not during ' + 'the previous render. Even though the final argument is optional, ' + 'its type cannot change between renders.', currentHookNameInDev);    }    return false;  }  {    // Don't bother comparing lengths in prod because these arrays should be    // passed inline.    if (nextDeps.length !== prevDeps.length) {      error('The final argument passed to %s changed size between renders. The ' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, "[" + prevDeps.join(', ') + "]", "[" + nextDeps.join(', ') + "]");    }  }  // 只有这部分是重要的,这里是做了浅比拟。  for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) {    if (objectIs(nextDeps[i], prevDeps[i])) {      continue;    }    return false;  }  return true;}