检查功能是否由useCallback创建?

时间:2020-09-08 03:00:01

标签: javascript reactjs react-hooks

我有一些接受函数作为参数的钩子。如果功能不必要地更改,则可能导致额外的重新渲染。我想确保这些函数用useCallback包装。

即这是一个简化的版本:

function useApi({ onSuccess }) {
  if (process.env.NODE_ENV !== 'production' && !isUseCallback(onSuccess)) {
    throw new Error();
  }

  useEffect(() => {
    fetch(...)
      .then(res => res.json())
      .then(onSuccess);
  }, [onSuccess]);
}

如果onSuccess不必要地更改,那么它将不必要地调用API。是否可以使用功能isUseCallback?我认为我必须编写一个包装React的useCallback的自定义useCallback

2 个答案:

答案 0 :(得分:0)

您可以将回调包装在useRef()中,以确保useEffect()回调具有对最新onSuccess的引用:

function useApi({ onSuccess }) {
  const ref = useRef();

  ref.current = onSuccess;

  useEffect(() => {
    fetch(...)
      .then(res => res.json())
      .then(val => ref.current(val));
  }, []);
}

重要的是,您编写.then(val => ref.current(val))而不是仅写.then(ref.current),以便在ref.current解析之前不会发生属性访问fetch()。这样,ref.current等于传递给onSuccess的最新useApi()

答案 1 :(得分:0)

我使用Typescript解决了这个问题

type UseCallback<T extends (...args: any[]) => any> =
  ((...args: Parameters<T>) => ReturnType<T>) & { __IS_USE_CALLBACK?: undefined };

declare function useCallback<T extends (...args: any[]) => any>(
  callback: T,
  deps: ReadonlyArray<any>,
): UseCallback<T>;

function useApi(onSuccess: UseCallback<() => any>): any;

useApi(() => {}); // Error
useApi(useCallback(() => {})); // No error