useCallback使用陷阱,你知道吗🤨

2021-11-05  本文已影响0人  前端小白的摸爬滚打

问题

useCallback和useMemo在起到缓存作用的时候我们需要注意的是,我们传入的函数也是具有闭包的效果的,也就是说,他们如果使用到了一些状态的时候也只能拿到当时函数执行的状态,所以我们需要把useMemo和useCallback中依赖的state作为他们的依赖项传入,以防止他们拿到的值是旧的值。

useCallback的缺点:

那么我们就会想:怎么可以让我们传入的函数返回一个引用一直不变且可以让传入的函数内部所使用的state都是最新的呢?很多人都会想到一个hook --- useRef

实现

import { useRef } from 'react';
export function useNewContextFn(fn: Function) {
  const fnRef = useRef(fn);
  // 每次组件更新时都更新fnRef的current属性,可以让我们的函数拿到最新的上下文
  fnRef.current = fn;
  const cacheRef = useRef((...args: any[]) => fn.current(...args));
  return cacheRef.current;
}

进阶版本,也许我们想要更多的函数都可以又这个效果

export default function useMethods<T extends Record<string, (...args: any[]) => any>>(methods: T) {
  const { current } = React.useRef({
    methods,
    func: undefined as T | undefined,
  });
  current.methods = methods;

  // 只初始化一次
  if (!current.func) {
    const func = Object.create(null);
    Object.keys(methods).forEach((key) => {
      // 包裹 function 转发调用最新的 methods
      func[key] = (...args: unknown[]) => current.methods[key].call(current.methods, ...args);
    });
    // 返回给使用方的变量
    current.func = func;
  }

  return current.func as T;
}

其实原理是一样的,看懂简易版本即可。😁

上一篇 下一篇

猜你喜欢

热点阅读