mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 19:33:46 +00:00
39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
/**
|
|
* Shamelessly from https://ahooks.js.org/hooks/use-memoized-fn/
|
|
* Interesting technique discussed by Dan Abramov
|
|
* https://overreacted.io/making-setinterval-declarative-with-react-hooks/
|
|
*/
|
|
|
|
import { useMemo, useRef } from 'react';
|
|
|
|
import { isDev } from '../../externals';
|
|
|
|
type noop = (this: any, ...args: any[]) => any;
|
|
|
|
type PickFunction<T extends noop> = (this: ThisParameterType<T>, ...args: Parameters<T>) => ReturnType<T>;
|
|
|
|
export const isFunction = (value: unknown): value is (...args: any) => any => typeof value === 'function';
|
|
|
|
export default function useMemoisedFn<T extends noop>(fn: T) {
|
|
if (isDev) {
|
|
if (!isFunction(fn)) {
|
|
console.error(`useMemoisedFn expected function as parameter, got ${typeof fn}`);
|
|
}
|
|
}
|
|
|
|
const fnRef = useRef<T>(fn);
|
|
|
|
// why not write `fnRef.current = fn`?
|
|
// https://github.com/alibaba/hooks/issues/728
|
|
fnRef.current = useMemo(() => fn, [fn]);
|
|
|
|
const memoizedFn = useRef<PickFunction<T>>();
|
|
if (!memoizedFn.current) {
|
|
memoizedFn.current = function (this, ...args) {
|
|
return fnRef.current.apply(this, args);
|
|
};
|
|
}
|
|
|
|
return memoizedFn.current as T;
|
|
}
|