diff --git a/src/hooks/useDelayState.ts b/src/hooks/useDelayState.ts index 978f7421..643dd0cd 100644 --- a/src/hooks/useDelayState.ts +++ b/src/hooks/useDelayState.ts @@ -3,7 +3,8 @@ import raf from '../raf'; import useEvent from './useEvent'; export type DelayConfig = - { frame: number; ms?: never } | { frame?: never; ms: number }; + | { frame: number; ms?: never } + | { frame?: never; ms: number }; export type SetDelayState = ( nextValue: React.SetStateAction, @@ -37,8 +38,11 @@ export default function useDelayState( } }); - const setDelayValue = useEvent>( - (nextValue, immediatelyOrDelay) => { + const setDelayValue = useEvent( + ( + nextValue: React.SetStateAction, + immediatelyOrDelay?: boolean | DelayConfig, + ) => { const delayConfig = immediatelyOrDelay || { frame: 1 }; cancelPending(); diff --git a/src/hooks/useEvent.ts b/src/hooks/useEvent.ts index d16360d1..49de15f1 100644 --- a/src/hooks/useEvent.ts +++ b/src/hooks/useEvent.ts @@ -1,21 +1,42 @@ -import * as React from 'react'; - -const useEvent = any) | undefined>( - callback: T, -): undefined extends T - ? ( - ...args: Parameters> - ) => ReturnType> | undefined - : T => { - const fnRef = React.useRef(callback); - fnRef.current = callback; - - const memoFn = React.useCallback( - (...args: any[]) => fnRef.current?.(...args), - [], - ); - - return memoFn; -}; +import React from 'react'; +import { useState } from 'react'; + +const useIsomorphicLayoutEffect = + typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect; + +type StableHandler = ( + this: This, + ...args: Args +) => Result; + +function useEvent( + fn: StableHandler, +): StableHandler; + +function useEvent< + This = unknown, + Args extends unknown[] = [], + Result = undefined, +>( + fn?: StableHandler, +): StableHandler; + +function useEvent( + callback?: StableHandler, +) { + const fnRef = React.useRef>(callback); + + useIsomorphicLayoutEffect(() => { + fnRef.current = callback; + }, [callback]); + + const [stableHandler] = useState(() => { + return function (this: This, ...args: Args) { + return fnRef.current?.apply(this, args); + }; + }); + + return stableHandler; +} export default useEvent;