useEventListener
Type-safe event listeners with automatic cleanup. Prevents memory leaks and duplicate listeners in React components.
Live Demo
Interact with the page to see different event listeners in action.
🖱️ Mouse Position
X: 0
Y: 0
⌨️ Keyboard Events
Last Key Pressed
—
🌐 Window Clicks
0
Total clicks anywhere
📦 Element-Specific Clicks
0
Click this box!
📝 Event Log
No events yet
💡 Try This:
- Move your mouse to see position tracking
- Press any key on your keyboard
- Click anywhere to increment window clicks
- Click the purple box to see element-specific events
Code Examples
Window Events
import { useEventListener } from "@uiblock/hooks";
import { useState } from "react";
export default function MouseTracker() {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEventListener('mousemove', (e) => {
setPosition({ x: e.clientX, y: e.clientY });
});
return <div>Mouse: {position.x}, {position.y}</div>;
}Element-Specific Events
import { useEventListener } from "@uiblock/hooks";
import { useRef, useState } from "react";
export default function ClickableBox() {
const [clicks, setClicks] = useState(0);
const boxRef = useRef<HTMLDivElement>(null);
useEventListener('click', () => {
setClicks(prev => prev + 1);
}, boxRef);
return (
<div ref={boxRef}>
Clicked {clicks} times
</div>
);
}Keyboard Shortcuts
import { useEventListener } from "@uiblock/hooks";
export default function KeyboardShortcuts() {
useEventListener('keydown', (e) => {
if (e.metaKey && e.key === 's') {
e.preventDefault();
console.log('Save shortcut triggered');
}
if (e.metaKey && e.key === 'k') {
e.preventDefault();
console.log('Search shortcut triggered');
}
});
return <div>Press Cmd+S or Cmd+K</div>;
}Scroll Events
import { useEventListener } from "@uiblock/hooks";
import { useState } from "react";
export default function ScrollIndicator() {
const [scrollY, setScrollY] = useState(0);
useEventListener('scroll', () => {
setScrollY(window.scrollY);
});
const scrollPercentage = (scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
return (
<div style={{ width: `${scrollPercentage}%`, height: 4, background: 'blue' }} />
);
}How It Works
Here's the implementation:
import { useEffect, useRef } from 'react'
export function useEventListener<K extends keyof WindowEventMap>(
eventName: K,
handler: (event: WindowEventMap[K]) => void,
element?: React.RefObject<HTMLElement>,
options?: boolean | AddEventListenerOptions
) {
const savedHandler = useRef(handler)
useEffect(() => {
savedHandler.current = handler
}, [handler])
useEffect(() => {
const targetElement = element?.current ?? window
if (!(targetElement && targetElement.addEventListener)) return
const eventListener = (event: Event) => {
savedHandler.current(event as WindowEventMap[K])
}
targetElement.addEventListener(eventName, eventListener, options)
return () => {
targetElement.removeEventListener(eventName, eventListener, options)
}
}, [eventName, element, options])
}Key Features:
- Automatic cleanup on unmount
- Type-safe event handlers
- Supports window, document, and element events
- Prevents memory leaks
API Reference
Parameters
eventName: stringName of the event to listen for
handler: (event) => voidEvent handler function
element?: RefObjectOptional element ref (defaults to window)
options?: AddEventListenerOptionsOptional event listener options
💡 Use Cases
- Mouse and keyboard event tracking
- Scroll position monitoring
- Window resize handlers
- Keyboard shortcuts
- Click outside detection
- Custom element interactions