我有一些接受函数作为参数的钩子。如果功能不必要地更改,则可能导致额外的重新渲染。我想确保这些函数用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
。
答案 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