React Hook源码笔记(十三):性能钩子-useCallback

66 阅读1分钟

博客:pionpill
官方文档: react.dev/reference/r…

上一篇文章讲的 memo 会缓存整个组件,这篇文章开始的几个 hook 则会缓存组件的部分属性。

useCallback 一般用于缓存函数,它有两个参数:

  • callback: 要缓存的函数
  • deps: 依赖数组

这里说的缓存是指:在依赖,状态等不改变的前提下,复用固有组件/属性以达到性能优化目的

mountCallback

首先看下 mount 阶段(✨约2780行):

function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
  const hook = mountWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

很简单,往 hookmemoizedState 里面塞了传进来的两个参数。

updateCallback

然后是更新阶段(✨约2787行):

function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
  const hook = updateWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  const prevState = hook.memoizedState;
  if (nextDeps !== null) {
    const prevDeps: Array<mixed> | null = prevState[1];
    // 依赖项相同,返回缓存的函数
    if (areHookInputsEqual(nextDeps, prevDeps)) {
      return prevState[0];
    }
  }
  // 否则,更新 memoizedState
  hook.memoizedState = [callback, nextDeps];
  return callback;
}

// 比较依赖项是否相同
function areHookInputsEqual(
  nextDeps: Array<mixed>,
  prevDeps: Array<mixed> | null,
): boolean {
  if (prevDeps === null) {
    return false;
  }

  for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
    if (is(nextDeps[i], prevDeps[i])) {
      continue;
    }
    return false;
  }
  return true;
}

实现很简单,看完前面几篇文章,简单看一下源代码就知道咋实现的了。