export default function useMouseHover()

in packages-hook/react-hook-mouse-hover/src/hook/use-mouse-hover.ts [37:116]


export default function useMouseHover({
  active,
  defaultActive,
  timeDelayEnter = 160,
  timeDelayLeave = timeDelayEnter,
  timeCoolDownActive = 300,
  onEnter,
  onLeave,
  onActiveChange
}: IOptions = {}): [() => void, () => void, () => void] {
  const isUnmounted = useIsUnmounted();
  const [controllableActive, setControllableActive] = useControllable<boolean>(false, active, defaultActive, onActiveChange);
  const refValue = useRef<IRefValue>({
    timer: null,
    timestampActiveByHover: 0
  });
  
  const handleClearTimer = useCallback(() => {
    if (refValue.current.timer) {
      window.clearTimeout(refValue.current.timer);
      
      refValue.current.timer = null;
    }
  }, [refValue]);
  
  /**
   * 鼠标移入,延时响应,避免误触发一些不必要的响应
   */
  const handleMouseEnter = useCallback(() => {
    handleClearTimer();
    
    refValue.current.timer = window.setTimeout(() => {
      if (isUnmounted()) {
        return;
      }
      
      refValue.current.timer = null;
      
      onEnter?.();
      
      if (!controllableActive) {
        refValue.current.timestampActiveByHover = Date.now();
        
        setControllableActive(true);
      }
    }, timeDelayEnter);
  }, [timeDelayEnter, onEnter, isUnmounted, controllableActive, setControllableActive, refValue, handleClearTimer]);
  /**
   * 鼠标移出,延时响应,类似 Dropdown 的组件,需要这样的能力
   */
  const handleMouseLeave = useCallback(() => {
    handleClearTimer();
    
    refValue.current.timer = window.setTimeout(() => {
      if (isUnmounted()) {
        return;
      }
      
      refValue.current.timer = null;
      
      onLeave?.();
    }, timeDelayLeave);
  }, [timeDelayLeave, onLeave, isUnmounted, refValue, handleClearTimer]);
  const handleActiveChange = useCallback(() => {
    handleClearTimer();
    
    const nextActive = !controllableActive;
    
    if (!nextActive) {
      if (refValue.current.timestampActiveByHover > 0 && Date.now() - refValue.current.timestampActiveByHover <= timeCoolDownActive) {
        return;
      }
    }
    
    handleClearTimer();
    setControllableActive(nextActive);
  }, [timeCoolDownActive, setControllableActive, controllableActive, handleClearTimer]);
  
  return [handleMouseEnter, handleMouseLeave, handleActiveChange];
}