1. import { useEffect, useRef, useState } from 'react';
    2. interface HoverOption {
    3. onEnter?: () => void;
    4. onLeave?: () => void;
    5. entryDelay?: number;
    6. leaveDelay?: number;
    7. }
    8. const DEFAULT_DELAY: HoverOption = {
    9. entryDelay: 100,
    10. leaveDelay: 500,
    11. };
    12. const useHover = <T extends HTMLElement>(options?: HoverOption) => {
    13. const { onEnter, onLeave, entryDelay, leaveDelay } = options || DEFAULT_DELAY;
    14. const domRef = useRef<T | null>(null);
    15. const [visible, setVisible] = useState(false);
    16. const timeRef = useRef<any>();
    17. const onMouseEnter = () => {
    18. clearTimeout(timeRef.current);
    19. timeRef.current = setTimeout(() => {
    20. setVisible(true);
    21. onEnter?.();
    22. }, entryDelay);
    23. };
    24. const onMouseLeave = () => {
    25. clearTimeout(timeRef.current);
    26. timeRef.current = setTimeout(() => {
    27. setVisible(false);
    28. onLeave?.();
    29. }, leaveDelay);
    30. };
    31. useEffect(() => {
    32. if (domRef.current) {
    33. domRef.current.addEventListener('mouseenter', onMouseEnter);
    34. domRef.current.addEventListener('mouseleave', onMouseLeave);
    35. }
    36. return () => {
    37. domRef.current?.removeEventListener('mouseenter', onMouseEnter);
    38. domRef.current?.removeEventListener('mouseleave', onMouseLeave);
    39. clearTimeout(timeRef.current);
    40. };
    41. }, []);
    42. return [visible, domRef, { setVisible }] as const;
    43. };
    44. export default useHover;