Docs
useEventListener

Automates retries of a callback function until it succeeds with useContinuousRetry.

Installation

pnpm dlx shadcn@latest add https://usekit.kiron.dev/k/use-event-listener

Usage

"use client"
 
import * as React from "react"
import { X } from "lucide-react"
 
import { useEventListener } from "@/hooks/use-event-listener"
 
export function Component() {
  const ref = React.useRef(null)
  const [isOpen, setIsOpen] = React.useState(false)
 
  const handleClick = (e) => {
    const element = ref.current
    if (element && !element.contains(e.target)) {
      setIsOpen(false)
    }
  }
 
  useEventListener(document, "mousedown", handleClick)
 
  return (
    <section>
      <h1>useEventListener</h1>
      <div style={{ minHeight: "200vh" }}>
        <button className="link" onClick={() => setIsOpen(true)}>
          Click me
        </button>
      </div>
      {isOpen && (
        <dialog ref={ref}>
          <button onClick={() => setIsOpen(false)}>
            <X />
          </button>
          <h2>Modal</h2>
          <p>
            Click outside the modal to close (or use the button) whatever you
            prefer.
          </p>
        </dialog>
      )}
    </section>
  )
}

Usage Examples

Standard DOM Element:

useEventListener(document, "mousedown", (e: MouseEvent) => {
  console.log("Document click:", e.clientX, e.clientY)
})

React Ref:

const buttonRef = useRef<HTMLButtonElement>(null)
 
useEventListener(buttonRef, "click", (e: MouseEvent) => {
  console.log("Button clicked!", e.currentTarget)
})

Window Events with Options:

useEventListener(window, "resize", () => console.log("Window resized"), {
  passive: true,
})

API Reference

Parameters

NameTypeDescriptionDefault ValueOptional
targetRefObject<Element> | Element | Window | Document | nullDOM element, React ref, or global target-No
eventNamestringEvent name to listen for (e.g., "click", "keydown")-No
handler(event: Event) => voidCallback function to execute when event occurs-No
options{ capture: boolean, passive: boolean, once: boolean }Event listener options{}Yes