function Window({ children, name }) {
const { modalName, closeModal } = useContext(ModalContext);
const ref = useOutsideClick(closeModal);
if (modalName !== name) return null;
return createPortal(
<Overlay>
<StyledModal ref={ref}>
<Button onClick={closeModal}>
<HiXMark />
</Button>
<div>
{cloneElement(children, {
onCloseModal: closeModal,
})}
</div>
</StyledModal>
</Overlay>,
document.body
);
}
const ref = useRef();
useEffect(() => {
function clickHandler(e) {
// check ref (generally modal self) if not clicked to it then close modal
if (ref.current && !ref.current.contains(e.target)) {
// generally closeModal function
fnHandler();
}
}
document.addEventListener("click", clickHandler, true);
return () => document.removeEventListener("click", clickHandler, true);
}, []);
return ref;
我正在使用 useOutsideClick 钩子,如果我不使用事件捕获,则 ref.current 被设置,但如果我不使用捕获,则未定义
当然!因此,看起来您正在考虑处理事件捕获,但在使用
useOutsideClick
钩子时却没有它。让我们来分解一下:
捕获事件与冒泡: 当您单击网站上的某些内容时,浏览器知道首先单击的内容,然后知道其中的内容。这个过程有两个阶段:捕获和冒泡。捕获从顶部开始向下移动,而胡言乱语从单击的项目开始向上移动。
为什么重要: 在您的
useOutsideClick
代码中,您使用事件捕获,浏览器会查找从顶部开始的点击。这很好,因为您想要捕获模式之外的点击。您传递一个 ref
,它有助于确定单击是在模式内部还是外部。日落时,效果很好。
捕获的物品: 如果没有捕获事件捕获,则单击从被单击的项开始,向上移动。在这种情况下,直到点击到达顶部之前,
ref.current
可能无法正确设置,从而导致一些混乱。
故事笔记: 您的人员需要捕获事件才能按预期工作。这确保您的
ref.current
可以正常运行,并且可以确定点击是在模式内部还是外部。这就像确保浏览器从顶部开始看哪个是哪个!