Skip to content

useEventListener

React hook to listen for events on a target element.

Add the hook via the CLI:

sh
npx @novajslabs/cli add useEventListener
sh
npx @novajslabs/cli add useEventListener
sh
pnpm dlx @novajslabs/cli add useEventListener

Or copy and paste the code into your project:

ts
import { useEffect, useRef } from "react";

export default function useEventListener(
  eventName: string,
  callback: EventListener,
  element: HTMLElement | (Window & typeof globalThis) | Document | null = window
) {
  const callbackRef = useRef<EventListener>(callback);

  useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);

  useEffect(() => {
    if (!(element && element.addEventListener)) {
      return;
    }

    const eventListener = (event: Event) => callbackRef.current(event);

    element.addEventListener(eventName, eventListener);

    return () => {
      element.removeEventListener(eventName, eventListener);
    };
  }, [eventName, element]);
}
js
import { useEffect, useRef } from "react";

export default function useEventListener(
  eventName,
  callback,
  element = window
) {
  const callbackRef = useRef(callback);

  useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);

  useEffect(() => {
    if (!(element && element.addEventListener)) {
      return;
    }

    const handler = (e) => callbackRef.current(e);

    element.addEventListener(eventName, handler);

    return () => {
      element.removeEventListener(eventName, handler);
    };
  }, [eventName, element]);
}

Requirements

React 16.8 or higher

Parameters

eventName required

Type: string

The type of event to listen for.

callback required

Type: EventListener

The function to be executed when the event occurs.

element

Type: HTMLElement | Window | Document | null

The target element to which the event listener is attached. Defaults to window.

Example

tsx
import { useRef, useState } from "react";
import useEventListener from "./hooks/useEventListener";

const App = () => {
  const [onClick, setOnClick] = useState(0);
  const [documentClick, setDocumentClick] = useState(0);
  const buttonRef = useRef<HTMLButtonElement | null>(null);

  useEventListener(
    "click",
    (e) => {
      e.preventDefault();
      e.stopPropagation();
      setOnClick(onClick + 1);
    },
    buttonRef.current
  );

  useEventListener("click", () => {
    setDocumentClick(documentClick + 1);
  });

  return (
    <>
      <button ref={buttonRef} onClick={() => setOnClick(onClick + 1)}>
        Clicked {onClick} times
      </button>

      <div style={{ marginTop: "1rem" }}>
        Document clicked {documentClick} times
      </div>
    </>
  );
};

export default App;

Use cases

Here are some use cases where this React hook is useful:

  • Monitoring clicks or keypresses to gather analytics or trigger specific actions
  • Dynamically triggering animations based on window size changes
  • Implementing custom drag-and-drop functionality by listening to mouse events

Released under the MIT License.