gpt4 book ai didi

javascript - 如何在使用 ReactDOM.createPortal() 的 child 上处理 ref.current.contains()?

转载 作者:行者123 更新时间:2023-12-04 01:21:08 25 4
gpt4 key购买 nike

我使用 React 钩子(Hook)创建了一个应用程序。我有一个辅助函数 onClickOutsideHook(ref, callback)触发 callback当您在提供 ref 的组件外部单击时使用 React.useRef :

export const onClickOutsideHook = (ref, callback) => {
// Hook get from https://stackoverflow.com/a/42234988/8583669

React.useEffect(() => {
const handleClickOutside = event => {
if (ref?.current && !ref.current.contains(event.target)) {
callback();
}
};
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [callback, ref]);
};
我有一个组件 Dropdown使用这个助手,所以当你点击它外面时它会关闭。该组件具有 Modal组件作为使用 ReactDOM.createPortal 的子组件.我用它来渲染 Modalbody所以它可以覆盖所有的应用程序屏幕。我的 Modal包含一个按钮,当您单击它时会提示一条消息:
function Modal() {
return ReactDOM.createPortal(
<div
style={{
position: "absolute",
top: 0,
left: 0,
height: "100%",
width: "100%",
background: "rgba(0,0,0,0.6)"
}}
>
<button onClick={() => alert("Clicked on Modal")}>Click</button>
</div>,
document.body
);
}

function Dropdown(props) {
const [isModalOpen, setIsModalOpen] = React.useState(false);

const dropdownRef = React.useRef(null);
onClickOutsideHook(dropdownRef, props.onClose);

return (
<div ref={dropdownRef}>
Click outside and I will close
<button onClick={() => setIsModalOpen(true)}>open Modal</button>
{isModalOpen ? <Modal /> : <></>}
</div>
);
}
问题是当我点击 Modal按钮触发警报, Dropdown之前关闭,因为我在它之外单击( Modal 不呈现为 Dropdown 的子级,而是在 body 中)。所以我的警报永远不会被触发。
有没有办法定义 Modal作为 Dropdown 的 child 使用 ref但仍然在 body 中渲染它使用 ReactDOM.createPortal ?
看看 CodeSandbox .

最佳答案

喜欢 Portals文档说:

Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way...

This includes event bubbling. An event fired from inside a portal willpropagate to ancestors in the containing React tree, even if thoseelements are not ancestors in the DOM tree.


但这里不是这样, 鼠标按下 事件监听器被添加到 文件 不仅是 下拉零件。即便如此,冒泡仍然发生。
这意味着如果您添加 引用 模态 ,然后在 上添加事件监听器鼠标按下 整个目的是阻止传播的事件, 处理点击外部 函数永远不会被调用。
它似乎仍然是一种解决方法,我不知道是否有适当的方法来检查。
function Modal() {
const modalRef = useRef();

useEffect(() => {
const stopPropagation = e => {
e.stopPropagation();
};

const { current: modalDom } = modalRef;
modalDom.addEventListener("mousedown", stopPropagation);

return () => {
modalDom.removeEventListener("mousedown", stopPropagation);
};
}, []);

return ReactDOM.createPortal(
<div
ref={modalRef}
style={{
position: "absolute",
top: 0,
left: 0,
height: "100%",
width: "100%",
background: "rgba(0,0,0,0.6)"
}}
>
<button onClick={() => alert("Clicked on Modal")}>Click</button>
</div>,
document.body
);
}
从以下 CodeSandbox 观看 Modal 组件.

关于javascript - 如何在使用 ReactDOM.createPortal() 的 child 上处理 ref.current.contains()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62638282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com