如何在 React 中偵測元素外部的點擊

偵測元素外部的點擊是 React 中最常見的 UI 模式之一。它對於在使用者點擊頁面其他位置時關閉模態框、下拉選單、彈出式選單和工具提示至關重要。

問題所在

在建構下拉選單或模態框等互動式元件時,你需要在使用者點擊外部任何位置時關閉它們。手動實作這個功能需要:

  1. 新增一個 document 層級的點擊事件監聽器
  2. 檢查點擊目標是在元素內部還是外部
  3. 在元件卸載時清除監聽器
  4. 處理邊界情況(portals、巢狀元素等)

手動實作方式

以下是大多數開發者從零開始實作的方式:

import { useEffect, useRef } from "react";

function Dropdown() {
  const ref = useRef(null);
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    function handleClick(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        setIsOpen(false);
      }
    }
    document.addEventListener("mousedown", handleClick);
    return () => document.removeEventListener("mousedown", handleClick);
  }, []);

  return <div ref={ref}>{/* dropdown content */}</div>;
}

這種方式可以運作,但你會在各處重複這個模式。而且它遺漏了觸控事件、iframe 點擊和 Shadow DOM 等邊界情況。

更好的方式:useClickOutside

ReactUse 提供了 useClickOutside,為你處理所有這些問題:

import { useClickOutside } from "@reactuses/core";
import { useRef, useState } from "react";

function Dropdown() {
  const ref = useRef(null);
  const [isOpen, setIsOpen] = useState(false);

  useClickOutside(ref, () => {
    setIsOpen(false);
  });

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Open Menu</button>
      {isOpen && (
        <div ref={ref}>
          <p>Click outside to close</p>
        </div>
      )}
    </div>
  );
}

常見使用情境

  • 模態對話框 — 點擊背景遮罩時關閉
  • 下拉選單 — 點擊選單外部時關閉
  • 工具提示/彈出框 — 在外部互動時消除
  • 搜尋自動完成 — 關閉建議面板
  • 右鍵選單 — 消除自訂的右鍵選單

線上體驗

查看我們文件網站上的互動式範例,你可以編輯程式碼並即時查看結果。

安裝

npm i @reactuses/core

相關 Hooks


ReactUse 提供超過 100 個 React hooks。探索所有 hooks →