custom hooks

useHover( )

The code provided in this article is simplified as much as possible to avoid overwhelming the reader with code and to convey the essence of the problem and its solution. In interactive examples, heading tags (`h1...h6`) are replaced with span tags to prevent potential conflicts with the main page structure.

Explanation

The useHover hook is a hook designed to simplify the process of tracking mouse hover interactions over specific DOM elements within a React component. By utilizing event listeners for mouseenter and mouseleave events, this hook allows developers to monitor whether the mouse cursor is currently hovering over a designated element. Upon detecting these events, the hook updates a boolean state to reflect the hover status, providing a straightforward way to incorporate hover functionality into React applications. Additionally, the hook handles the cleanup of event listeners to ensure proper resource management and prevent memory leaks, enhancing the overall robustness and efficiency of hover tracking within React components.

Using this hook simplifies the creation of interactive user interfaces, such as tooltips, animations, or style changes based on mouse hover states. It's also worth noting that the hook provides a flexible and easily configurable way to track mouse hover, allowing developers to create interactive and intuitive web applications.

Usage Cases

  • Adding and Removing Classes: Leveraging a hover-based approach to dynamically add or remove CSS classes, enabling the creation of different styles for elements during hover.
  • Changing Styles: Adjusting element styles on hover, such as text color, background image, or font size, to enhance visual appeal and user interaction.
  • Tooltip Display: Displaying tooltips when the mouse hovers over specific elements, providing additional context or information to users.
  • Interactive Menus: Creating interactive menus or dropdowns that expand or show additional options when hovered over, improving navigation and user experience.
  • Image Galleries: Enhancing image galleries by displaying image captions or controls when the mouse hovers over the image, providing users with more interaction options.
  • Interactive Cards: Building interactive card components that change appearance or display additional content when hovered over, improving user engagement and interaction with content.
  • Hover Effects: Implementing hover effects such as animations, transitions, or color changes to enhance the visual feedback when interacting with elements on the page.
  • Altering Behavior: Adjusting element behavior on hover, such as showing or hiding additional interface elements, triggering animations, or invoking other actions upon interaction with elements.

Creation

Code implementation
1const useHover = (ref: RefObject<HTMLElement>): boolean => {
2 // Define a state variable to track whether the element is being hovered
3 const [isHovering, setHovering] = useState(false);
4
5 // Set up an effect to attach event listeners for `mouseenter` and
6 // `mouseleave` events when the component mounts or when the `ref` changes
7 useEffect(() => {
8 // Check if the `ref` is pointing to a valid DOM element
9 if (!ref.current) {
10 return;
11 }
12
13 // Retrieve the DOM node from the `ref` for convenience
14 const node = ref.current;
15
16 // Define event handler functions to set the `isHovering` state accordingly.
17 // By defining them within the effect, we avoid the need to include them in the dependency array
18 const onEnter = () => setHovering(true);
19 const onLeave = () => setHovering(false);
20
21 // Attach event listeners for `mouseenter` and `mouseleave` events to the DOM node.
22 // You can replace `mouseenter` and `mouseleave` with `pointerenter` and `pointerleave`.
23 // Unlike `mouseenter`, the `pointerenter` event bubbles, meaning it can be captured
24 // on a parent element when the mouse pointer enters its child elements.
25 // `pointerenter` also supports a wider range of input devices,
26 // such as styluses and touch screens, providing better compatibility and versatility
27 node.addEventListener('mouseenter', onEnter);
28 node.addEventListener('mouseleave', onLeave);
29
30 // Return a cleanup function to remove event listeners
31 // when the component unmounts or when the `ref` changes
32 return () => {
33 node.removeEventListener('mouseenter', onEnter);
34 node.removeEventListener('mouseleave', onLeave);
35 };
36 }, [ref]); // Include the `ref` in the dependency array to ensure the `useEffect` runs when the `ref` changes
37
38 return isHovering;
39};
40
41export default useHover;
42

Reference

Code implementation
1const isHovering = useHover(ref);
2

Parameters

NameTypeDescription
refRefObject<HTMLElement>Represents a reference to the DOM element for which the mouse hover state is being tracked.

Return values

NameTypeDescription
isHoveringbooleanThe indication of whether the element is currently being hovered over.

Example Usages

Interactive Hover Menu

This example showcases an interactive hover menu utilizing a custom useHover hook. Alongside toggling between a hamburger and close icon upon hover, the menu itself dynamically appears when hovered over. Leveraging the useHover hook optimizes event handling for seamless user interaction, enhancing the overall functionality of the React component.

Code implementation
1const menuItems = loadData(3);
2
3const Container: FC = () => {
4 // Creating a reference to be attached to the DOM element
5 const elementRef = useRef<HTMLDivElement | null>(null);
6
7 // Utilize the custom hook `useHover` to determine if the element is being hovered
8 const isHovered = useHover(elementRef);
9
10 const handleClick = () => {};
11
12 return (
13 <Layer title="Container">
14 <div className="flex items-center justify-center">
15 <div
16 // Assigning the `ref` to the `div` element,
17 // allowing it to be tracked by the `useHover` hook
18 ref={elementRef}
19 className="relative"
20 >
21 <div className="relative flex h-14 w-14 items-center justify-center rounded-xl bg-blue-500 text-white">
22 {isHovered ? <IconClose /> : <IconOpen />}
23 </div>
24 {/* Conditionally render menu based on `isHovered` state */}
25 {isHovered && (
26 <div className="absolute -top-2 left-14 w-40 p-2">
27 <List
28 items={menuItems}
29 onClick={handleClick}
30 />
31 </div>
32 )}
33 </div>
34 </div>
35 </Layer>
36 );
37};
38
An interactive output of the code above

Interactive Term Card

This example illustrates an interactive term card utilizing a custom useHover hook. The card conditionally displays term discription upon hover. Leveraging the useHover hook enhances user interaction by efficiently managing isCardHovered state within the React component.

Code implementation
1const term = {
2 title: '"Closure"',
3 discription: `A closure is the combination of a function bundled together
4 (enclosed) with references to its surrounding state (the lexical environment).`,
5};
6
7const Container: FC = () => {
8 // Create a reference to a DOM element
9 const elementRef = useRef<HTMLDivElement | null>(null);
10
11 // Utilize the custom hook `useHover` to determine if the element is being hovered
12 const isCardHovered = useHover(elementRef);
13
14 return (
15 <Layer title="Container">
16 <Text
17 ref={elementRef}
18 className="h-48"
19 >
20 {
21 // Conditional rendering of content based on `isCardHovered` state
22 isCardHovered ? term.discription : term.title
23 }
24 </Text>
25 </Layer>
26 );
27};
28
An interactive output of the code above
Last updated on by @skrykateSuggest an improvement on Github repository.