Open Hooks
Event Handling

useClickOutside

Detect clicks outside a specific element to trigger a callback function.

useClickOutside

Detect clicks outside a specific element to trigger callbacks like closing modals or dropdowns.

Status: stable
Version: 1.2.0
Bundle Size: ~0.8kb
Requires: React 16.8+

Installation

npx open-hook add useClickOutside
yarn dlx open-hook add useClickOutside
pnpm dlx open-hook add useClickOutside

API Reference

Parameters

PropTypeDefault
callback?
() => void
-
ref?
React.RefObject<HTMLElement>
-

Returns

No Return Value

This hook performs a side effect and does not return any value.

TypeScript Signature

function useClickOutside(
  ref: React.RefObject<HTMLElement>,
  callback: () => void
): void;

Best Practices

Use useCallback for the callback function to prevent unnecessary re-renders:

const handleClose = useCallback(() => {
  setIsOpen(false);
}, []);

useClickOutside(modalRef, handleClose);

Do's and Don'ts

  • ✅ Use useCallback for static callbacks
  • ✅ Ensure the ref is properly attached to the target element
  • ✅ Consider using useRef for better performance
  • ❌ Avoid using this hook with frequently changing callbacks without memoization
  • ❌ Don't forget to handle cases where the ref might be null

Performance Metrics

MetricValueDescription
Bundle Size~0.8kbMinified + gzipped
Re-rendersNoneOnly side effect, no state
MemoryMinimalSingle event listener
First Paint+0msNo blocking operations

Browser Compatibility

BrowserSupportedNotes
Chrome (latest)YesFull support
Firefox (latest)YesFull support
Safari (latest)YesFull support
Edge (latest)YesFull support
IE 11NoNot supported
Node.jsYesFor SSR environments

Use Cases

Modal Dialogs

Perfect for closing modals when users click outside the modal area.

Dropdown Menus

Close dropdown menus when clicking elsewhere on the page.

Search Suggestions

Hide search suggestion panels when clicking outside the search box.

Mobile Sidebars

Collapse navigation sidebars on mobile when tapping outside.

Accessibility

Accessibility Considerations

  • The hook respects keyboard navigation and only handles mouse events - Consider adding Escape key support for better accessibility - Ensure focus management is handled separately for screen readers

Troubleshooting

Internals

How It Works

The hook uses a single mousedown event listener on the document to detect clicks. When a click occurs, it checks if the clicked element is contained within the referenced element using Node.contains(). If the click is outside, it triggers the provided callback.

The event listener is automatically cleaned up when the component unmounts or dependencies change.

Testing Example

import { renderHook } from "@testing-library/react";
import { useRef } from "react";
import { useClickOutside } from "./useClickOutside";

it("calls callback when clicking outside element", () => {
  const callback = jest.fn();
  const ref = { current: document.createElement("div") };

  renderHook(() => useClickOutside(ref, callback));

  // Simulate click outside
  const outsideElement = document.createElement("div");
  document.body.appendChild(outsideElement);

  const event = new MouseEvent("mousedown", { bubbles: true });
  outsideElement.dispatchEvent(event);

  expect(callback).toHaveBeenCalledTimes(1);
});

FAQ

Changelog

  • 1.1.0 — Added better TypeScript support and performance optimizations
  • 1.0.0 — Initial release with basic click outside detection