React钩子事件监听器内更新状态导致元素默认行为失效
问题原因与修复方案
你的问题出在当前钩子没有区分点击事件是发生在目标div内部还是外部,导致点击菜单内的按钮时也会触发onClickOutside,执行setIsMenuOpen(false)关闭菜单——菜单组件卸载/重新渲染的过程会中断按钮的默认滚动行为。
修复后的钩子代码
export function useClickOutside({ ref, onClickOutside, }: { ref: React.RefObject<HTMLElement>; onClickOutside: () => void; }) { useEffect(() => { function handleClickOutside(event: MouseEvent) { // 仅当点击目标不在ref指向的元素内部时,才执行外部点击逻辑 if (ref.current && !ref.current.contains(event.target as Node)) { onClickOutside(); } } document.addEventListener("pointerdown", handleClickOutside); return () => { document.removeEventListener("pointerdown", handleClickOutside); }; }, [ref, onClickOutside]); // 添加依赖数组,避免重复绑定事件 }
关键修复点
- 添加内部点击判断:通过
ref.current.contains(event.target as Node)检查点击位置,只有外部点击才触发状态更新,菜单内的点击不会触发关闭逻辑,按钮的默认滚动行为可以正常完成。 - 补充useEffect依赖数组:避免组件每次渲染都重复绑定/解绑事件,优化性能的同时防止不必要的副作用触发。
内容的提问来源于stack exchange,提问作者Nithin K
相关产品推荐
相关产品推荐

