Skip to main content

Usage

Attaches an event listener to a target (element ref, window, or document) and automatically removes it on cleanup.
import { useRef } from 'react';
import { useEventListener } from '@kivora/react';

function KeyboardHandler() {
  const handler = (event: KeyboardEvent) => {
    console.log('Key pressed:', event.key);
  };

  useEventListener('keydown', handler);

  return <div>Press any key</div>;
}

Parameters

event
string
required
Event name to listen for (e.g., 'click', 'keydown', 'resize')
handler
(event: Event) => void
required
Callback function invoked when the event occurs
target
RefObject<EventTarget | null>
default:"{ current: window }"
Target to attach the listener to. Can be a ref to an element, { current: window }, or { current: document }
options
boolean | AddEventListenerOptions
Event listener options (e.g., { passive: true, capture: true })

Returns

void - This hook does not return a value.

Examples

Listen to window resize

import { useState } from 'react';
import { useEventListener } from '@kivora/react';

function WindowSize() {
  const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

  useEventListener(
    'resize',
    () => setSize({ width: window.innerWidth, height: window.innerHeight }),
    { current: window }
  );

  return (
    <div>
      Window size: {size.width} x {size.height}
    </div>
  );
}

Listen to element clicks

import { useRef } from 'react';
import { useEventListener } from '@kivora/react';

function ClickableBox() {
  const ref = useRef<HTMLDivElement>(null);

  useEventListener(
    'click',
    (event: MouseEvent) => {
      console.log('Box clicked at:', event.clientX, event.clientY);
    },
    ref
  );

  return (
    <div ref={ref} style={{ width: '200px', height: '200px', background: '#eee' }}>
      Click me
    </div>
  );
}

Keyboard shortcuts

import { useEventListener } from '@kivora/react';

function KeyboardShortcuts() {
  useEventListener('keydown', (event: KeyboardEvent) => {
    if (event.metaKey && event.key === 's') {
      event.preventDefault();
      console.log('Save triggered');
    }
    if (event.metaKey && event.key === 'k') {
      event.preventDefault();
      console.log('Search triggered');
    }
  });

  return <div>Press Cmd+S to save, Cmd+K to search</div>;
}

Document click tracking

import { useState } from 'react';
import { useEventListener } from '@kivora/react';

function ClickCounter() {
  const [clicks, setClicks] = useState(0);

  useEventListener(
    'click',
    () => setClicks((c) => c + 1),
    { current: document }
  );

  return <div>Total clicks on page: {clicks}</div>;
}

Scroll with passive listener

import { useState, useRef } from 'react';
import { useEventListener } from '@kivora/react';

function ScrollTracker() {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);

  useEventListener(
    'scroll',
    (event: Event) => {
      const target = event.target as HTMLDivElement;
      setScrollTop(target.scrollTop);
    },
    containerRef,
    { passive: true }
  );

  return (
    <div>
      <div>Scrolled: {scrollTop}px</div>
      <div ref={containerRef} style={{ height: '200px', overflow: 'auto' }}>
        <div style={{ height: '1000px' }}>Scroll me</div>
      </div>
    </div>
  );
}

Build docs developers (and LLMs) love