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];
}