@codegouvfr/react-dsfr
Version:
French State Design System React integration library
50 lines (42 loc) • 1.5 kB
text/typescript
import { useRef, useState } from "react";
import { id } from "tsafe/id";
import { memoize } from "../memoize";
export type CallbackFactory<FactoryArgs extends unknown[], Args extends unknown[], R> = (
...factoryArgs: FactoryArgs
) => (...args: Args) => R;
/**
* https://docs.powerhooks.dev/api-reference/usecallbackfactory
*
* const callbackFactory= useCallbackFactory(
* ([key]: [string], [params]: [{ foo: number; }]) => {
* ...
* },
* []
* );
*
* WARNING: Factory args should not be of variable length.
*
*/
export function useCallbackFactory<
FactoryArgs extends (string | number | boolean)[],
Args extends unknown[],
R = void
>(callback: (...callbackArgs: [FactoryArgs, Args]) => R): CallbackFactory<FactoryArgs, Args, R> {
type Out = CallbackFactory<FactoryArgs, Args, R>;
const callbackRef = useRef<typeof callback>(callback);
callbackRef.current = callback;
const memoizedRef = useRef<Out | undefined>(undefined);
return useState(() =>
id<Out>((...factoryArgs) => {
if (memoizedRef.current === undefined) {
memoizedRef.current = memoize(
(...factoryArgs: FactoryArgs) =>
(...args: Args) =>
callbackRef.current(factoryArgs, args),
{ "argsLength": factoryArgs.length }
);
}
return memoizedRef.current(...factoryArgs);
})
)[0];
}