You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中实现点击任意位置关闭Dropdown的功能

修复点击外部关闭下拉菜单的逻辑

你的useClickOutside Hook的点击判断逻辑存在错误,导致当前行为不符合预期。正确的逻辑应该是:当点击事件的目标不在下拉菜单元素内部时,触发关闭回调。

修正后的useClickOutside Hook

import { useEffect, useRef } from "react";

export function useClickOutside(callback: () => void) {
  const ref = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    function handleClick(event: MouseEvent) {
      // 确认ref已挂载,且点击目标不在下拉菜单元素范围内
      if (ref.current && !ref.current.contains(event.target as Node)) {
        callback();
      }
    }

    window.addEventListener("click", handleClick, { capture: true });
    return () => {
      window.removeEventListener("click", handleClick, { capture: true });
    };
  }, [callback]);

  return ref;
}

原代码的问题点

  • 判断逻辑完全颠倒:原代码用target?.contains(ref.current)判断,实际应该检查点击目标是否被ref.current包含
  • 错误的依赖项:useEffect中加入ref.current毫无意义,useRef的current值变更不会触发副作用重执行
  • 冗余判断:event.target === ref.current的判断多余,contains方法已经包含元素自身的情况
  • 无用导入:toUSVString未被使用,可直接移除

调整DropDown组件

点击菜单按钮时需要阻止事件冒泡,避免刚打开菜单就被外部点击逻辑误关闭:

import { ReactNode, MouseEvent } from "react";
import { useClickOutside } from "../../util/hooks/useClickOutside";

export default function DropDown({
  id,
  onOpen,
  onClose,
  isOpen,
  content,
  buttonContent,
}: {
  id: string;
  onOpen: (id: string) => void | undefined;
  onClose: () => void | undefined;
  isOpen: boolean;
  content?: ReactNode;
  buttonContent?: any;
}) {
  const elementRef = useClickOutside(() => {
    if (isOpen) {
      onClose();
    }
  });

  const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();
    isOpen ? onClose() : onOpen(id);
  };

  return (
    <div className="relative z-30">
      <button
        className="rounded-full p-0 border-2 border-slate-300"
        onClick={handleButtonClick}
      >
        {buttonContent}
      </button>
      {isOpen && (
        <div
          ref={elementRef}
          className="absolute space-y-2 right-0 w-56 mt-2 origin-top-right bg-white rounded-lg shadow-xl ring-1 ring-black ring-opacity-5 focus:outline-none z-30"
        >
          {content}
        </div>
      )}
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Benjamin Kalungi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:36:59