useHooks.iov4.1.2
DocsBlogGitHub
Hooks
No hooks found in any category.

useHover

sensors

Installation

npx usehooks-cli@latest add use-hover

Description

A React hook for detecting when an element is being hovered with optional callbacks, delay support, and TypeScript generics for element types.

Parameters

NameTypeDefaultDescription
options?UseHoverOptions{}Configuration options for hover behavior

Return Type

UseHoverReturn<T>
PropertyTypeDescription
isHoveredbooleanWhether the element is currently being hovered
refReact.RefObject<T>Ref to attach to the element you want to detect hover on

Examples

Basic Hover Detection

Simple hover state detection

1const { isHovered, ref } = useHover(); 2 3return ( 4 <div 5 ref={ref} 6 style={{ 7 padding: '20px', 8 backgroundColor: isHovered ? 'lightblue' : 'lightgray' 9 }} 10 > 11 {isHovered ? 'Hovered!' : 'Hover me'} 12 </div> 13);

With Callbacks and Delay

Using hover with callbacks and delay

1const { isHovered, ref } = useHover({ 2 onHoverStart: () => console.log('Hover started'), 3 onHoverEnd: () => console.log('Hover ended'), 4 delay: 300 // 300ms delay 5}); 6 7return ( 8 <button ref={ref}> 9 {isHovered ? 'Hovering...' : 'Hover me (with delay)'} 10 </button> 11);

Dependencies

react

Notes

  • Automatically cleans up event listeners on unmount
  • Supports delay for hover start but immediate hover end
  • Uses TypeScript generics for type-safe element references
  • Handles timeout cleanup to prevent memory leaks

Implementation

1'use client'; 2 3import { useState, useCallback, useRef, useEffect } from "react"; 4 5interface UseHoverOptions { 6 onHoverStart?: () => void; 7 onHoverEnd?: () => void; 8 delay?: number; 9} 10 11interface UseHoverReturn<T extends HTMLElement = HTMLElement> { 12 isHovered: boolean; 13 ref: React.RefObject<T>; 14} 15 16export const useHover = <T extends HTMLElement = HTMLElement>( 17 options: UseHoverOptions = {} 18): UseHoverReturn<T> => { 19 const [isHovered, setIsHovered] = useState(false); 20 const ref = useRef<T>(null); 21 const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null); 22 23 const { onHoverStart, onHoverEnd, delay = 0 } = options; 24 25 const handleMouseEnter = useCallback(() => { 26 if (timeoutRef.current) { 27 clearTimeout(timeoutRef.current); 28 timeoutRef.current = null; 29 } 30 31 if (delay > 0) { 32 timeoutRef.current = setTimeout(() => { 33 setIsHovered(true); 34 onHoverStart?.(); 35 }, delay); 36 } else { 37 setIsHovered(true); 38 onHoverStart?.(); 39 } 40 }, [onHoverStart, delay]); 41 42 const handleMouseLeave = useCallback(() => { 43 if (timeoutRef.current) { 44 clearTimeout(timeoutRef.current); 45 timeoutRef.current = null; 46 } 47 48 setIsHovered(false); 49 onHoverEnd?.(); 50 }, [onHoverEnd]); 51 52 useEffect(() => { 53 const element = ref.current; 54 if (!element) return; 55 56 element.addEventListener("mouseenter", handleMouseEnter); 57 element.addEventListener("mouseleave", handleMouseLeave); 58 59 return () => { 60 element.removeEventListener("mouseenter", handleMouseEnter); 61 element.removeEventListener("mouseleave", handleMouseLeave); 62 63 if (timeoutRef.current) { 64 clearTimeout(timeoutRef.current); 65 } 66 }; 67 }, [handleMouseEnter, handleMouseLeave]); 68 69 // Cleanup timeout on unmount 70 useEffect(() => { 71 return () => { 72 if (timeoutRef.current) { 73 clearTimeout(timeoutRef.current); 74 } 75 }; 76 }, []); 77 78 return { 79 isHovered, 80 ref: ref as React.RefObject<T>, 81 }; 82}; 83