useCallback的使用场景

201 阅读1分钟

最近在学习react的性能优化,看到了很多useCallback的文章,以下是我的理解。

看源码可以知道,useCallback包过的函数,不管依赖值更没更新,都会重新创建这个函数,但创建函数的性能消耗是很小的,然后useCallback为了去对比依赖值,会把上次的函数也存下来,再去对比这两次的依赖值,所以不要滥用useCallback,这些存储都是会影响性能的

    function updateCallback<T>(
      callback: T, // useCallback 的第一个参数
      deps: Array<mixed> | void | null // useCallback 的第二个参数
    ): T {

    // 取到当前的 useCallback 语句对应的 hook 节点,
    const hook = updateWorkInProgressHook();

    // 当前的依赖,后面拿来和上一次的依赖进行比较
    const nextDeps = deps === undefined ? null : deps;

    // 取到上一次缓存的函数
    const prevState = hook.memoizedState;
    if (prevState !== null) {
      // 传了 useCallbck 的第二个参数才走到这里
      if (nextDeps !== null) {
        const prevDeps: Array<mixed> | null = prevState[1];
        // 上一次的依赖和这一次的依赖进行比较,
        // 相同就直接返回缓存的结果
        if (areHookInputsEqual(nextDeps, prevDeps)) {
          return prevState[0];
        }
      }
    }
    hook.memoizedState = [callback, nextDeps];
    return callback;
    }

最合适的场景就是再给子组件传函数的时候,并且这个子组件是有写React.memo或者shouldComponentsUpdate时,才会去比较porps的参数来决定要不要重新渲染整个子组件,而且我们都知道就算函数内容没变化,相比之下也是false,这时用useCallback包住,让他返回上次的函数,子组件就不会重新渲染了。

() => {} === () => {}  // false