Home > @cascadiacollections/fluentui-compat > useOnEvent
useOnEvent() function
Hook to attach event listeners to window or document with automatic cleanup.
This hook provides a declarative way to manage event listeners that: - **Automatically cleans up**: Removes listeners on unmount or when dependencies change - **Type safe**: Full TypeScript support for event types - **Performance optimized**: Uses stable callbacks to prevent re-registration - **SSR safe**: Handles server-side rendering gracefully - **Flexible target**: Supports window, document, or any event target
**Common use cases**: - Window resize, scroll events - Document click/keydown for global interactions - Custom events on event targets - Keyboard shortcuts - Outside click detection
Signature:
export declare function useOnEvent<K extends keyof WindowEventMap>(target: Window | null | undefined, eventName: K, handler: (event: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
Parameters
|
Parameter |
Type |
Description |
|---|---|---|
|
target |
Window | null | undefined |
The event target (window, document, or EventTarget), or null to skip |
|
eventName |
K |
The name of the event to listen for |
|
handler |
(event: WindowEventMap[K]) => void |
The event handler callback |
|
options |
boolean | AddEventListenerOptions |
(Optional) Optional event listener options (capture, passive, once) |
Returns:
void
Example 1
// Window resize listener
function ResponsiveComponent() {
const [width, setWidth] = useState(window.innerWidth);
useOnEvent(window, 'resize', () => {
setWidth(window.innerWidth);
});
return <div>Window width: {width}px</div>;
}
Example 2
// Keyboard shortcuts
function KeyboardShortcuts() {
const [lastKey, setLastKey] = useState('');
useOnEvent(document, 'keydown', (event: KeyboardEvent) => {
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('Save shortcut triggered');
}
setLastKey(event.key);
});
return <div>Last key pressed: {lastKey}</div>;
}
Example 3
// Outside click detection
function Dropdown() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
useOnEvent(document, 'mousedown', (event: MouseEvent) => {
if (isOpen && dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
});
return (
<div ref={dropdownRef}>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && <div>Dropdown content</div>}
</div>
);
}
Example 4
// With event options (passive for scroll performance)
function ScrollTracker() {
const [scrollY, setScrollY] = useState(0);
useOnEvent(
window,
'scroll',
() => {
setScrollY(window.scrollY);
},
{ passive: true } // Improves scroll performance
);
return <div>Scroll position: {scrollY}px</div>;
}
Example 5
// Conditional event listening
function ConditionalListener({ shouldListen }: { shouldListen: boolean }) {
const [clicks, setClicks] = useState(0);
// Pass null to skip event listener registration
useOnEvent(
shouldListen ? document : null,
'click',
() => setClicks(c => c + 1)
);
return <div>Document clicks: {clicks}</div>;
}
Example 6
// Custom events
function CustomEventListener() {
const [data, setData] = useState<any>(null);
useOnEvent(window, 'my-custom-event', (event: Event) => {
setData((event as CustomEvent).detail);
});
return <div>Custom event data: {JSON.stringify(data)}</div>;
}