关于react.js:react-hooks-本质探索-useCallback源码解析

3次阅读

共计 1931 个字符,预计需要花费 5 分钟才能阅读完成。

这次来看 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;
}
正文完
 0