Skip to content

useHover

Edit

Tracks pointer hover for an element assigned through a callback ref.

useHover.ts
import { useCallback, useEffect, useState } from "react";
import type { RefCallback } from "react";
export interface UseHoverReturn<ElementType extends Element> {
isHovered: boolean;
ref: RefCallback<ElementType>;
}
/** Tracks pointer hover for a node assigned through the returned callback ref. */
export const useHover = <ElementType extends Element = HTMLElement>(
enabled: boolean = true,
): UseHoverReturn<ElementType> => {
const [node, setNode] = useState<ElementType | null>(null);
const [isHovered, setIsHovered] = useState(false);
const ref = useCallback<RefCallback<ElementType>>((nextNode) => {
setNode(nextNode);
setIsHovered(false);
}, []);
useEffect(() => {
if (!enabled || node === null) {
setIsHovered(false);
return;
}
const enter = () => setIsHovered(true);
const leave = () => setIsHovered(false);
node.addEventListener("pointerenter", enter);
node.addEventListener("pointerleave", leave);
return () => {
node.removeEventListener("pointerenter", enter);
node.removeEventListener("pointerleave", leave);
};
}, [enabled, node]);
return { isHovered, ref };
};
Terminal
wget -O src/hooks/useHover.ts https://raw.githubusercontent.com/jrTilak/lazykit/HEAD/registry/react-hooks/useHover.ts
useHover.example.tsx
import { useHover } from "./useHover";
export const HoverExample = () => {
const { ref, isHovered } = useHover<HTMLDivElement>();
return (
<div ref={ref} tabIndex={0}>
{isHovered ? "Pointer is inside" : "Hover this area"}
</div>
);
};
  • enabled (boolean) — Enables pointer listeners. Defaults to true.
  • ElementType — Generic element type attached to the callback ref.

UseHoverReturn<ElementType> with ref and isHovered.