React下拉菜单点击外部关闭生效,菜单内按钮无法点击如何解决?
问题根源
内部按钮无法触发点击的核心原因有3个:
- 未声明绑定
refContainer,导致refContainer.current.contains(e.target)的判断逻辑完全失效,点击菜单内部区域时也会触发setChoose(false)关闭菜单 - 全局绑定的
mousedown事件触发优先级高于元素自身的click事件,点击内部按钮时会先触发mousedown回调把菜单销毁,等click事件冒泡时元素已经不存在,自然无法触发绑定的点击事件 - 触发按钮的
onClick调用逻辑错误,直接给toggleChoose传了布尔值,而非预期的事件对象,逻辑冲突
调整方案
按以下步骤修改即可解决:
- 新增
useRef声明,绑定到最外层容器,让容器可以正确识别所有内部元素(包括触发按钮和下拉菜单) - 拆分菜单切换逻辑,区分主动点击触发按钮的切换操作和全局点击的关闭逻辑
- 增加菜单展开状态判断,只有菜单展开时才执行外部点击关闭的逻辑,避免无效状态更新
修正后完整代码
import { useState, useEffect, useRef } from 'react'; export const Something = () => { const [choose, setChoose] = useState(true) const [schedule, setSchedule] = useState(true) // 新增ref声明,绑定到外层容器 const refContainer = useRef(null) useEffect(() => { const handleClickOutside = (e) => { // 只有菜单展开时才判断是否点击外部 if (!choose && refContainer.current && !refContainer.current.contains(e.target)) { setChoose(true) } } document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; // 依赖项添加choose,保证判断逻辑实时正确 }, [choose]); // 主动点击触发按钮切换菜单显示 const toggleMenu = () => { setChoose(!choose) } const toggleSchedule = () => { setSchedule(!schedule) setChoose(!choose) } return <div className={styles.container} ref={refContainer}> <button onClick={toggleMenu}> <span>Choose </span> </button> {!choose && ( <div className={styles.containerInside}> <button onClick={toggleSchedule}>Other button to be clickable</button> </div> )} </div> }
内容的提问来源于stack exchange,提问作者lilo
相关产品推荐
相关产品推荐

