reactjs - React - 带有 `document.body` 的`createPortal` 导致点击事件立即触发
问题描述
我的应用程序有一个名为Open Modal
. 单击此按钮时,将向document.body
using附加一个模式createPortal
。演示链接
一旦安装了模式(即isOpen === true
),我想在每次用户单击页面上的某个位置时将一些文本打印到控制台。
为此,我使用useEffect
钩子将点击事件绑定到document
对象,如果isOpen === true
:
useEffect(() => {
const eventHandler = () => console.log("You clicked me");
if (isOpen) {
document.addEventListener("click", eventHandler);
}
}, [isOpen]);
当用户第一次点击“Open Modal”时,isOpen
从false
变为true
,这会导致组件重新渲染。重新渲染完成后,注册上述效果中的点击事件。
问题
第一次单击 'Open Modal' 会document
触发 'click 事件(您可以在控制台中看到事件处理程序的输出)。这对我来说没有意义 -当第一次“打开模式”点击传播到它时,点击事件怎么可能已经注册?document
预期行为
第一次点击 'Open Modal' 只会导致document
'click 事件被注册,此时事件本身不应触发。
如果我省略createPortal
(参见演示的第 38 行),应用程序将按预期工作,即在第一次单击“打开模式”时注册事件,并在页面上的所有后续单击时调用事件处理程序。
如果我将模式安装到应用程序根目录的同级而不是document.body
(参见演示的第 39 行),该应用程序也可以按预期工作。所以上面描述的问题只有在createPortal
使用 withdocument.body
作为容器时才会出现,但我不明白为什么。
解决方案
我不确定,但我认为,问题的发生是因为Event Propagation
,在传播完成时,文档click
事件已被注册,这可能是它调用eventHandler
. 如果我错了,请纠正我。
如果您停止事件传播,它工作正常。
const openModal = useCallback(
function (e) {
if (!isOpen) { // stopping the propagation
e.stopPropagation();
}
setOpen(true);
},
[setOpen, isOpen]
);
演示链接在这里
推荐阅读
- c# - Unity 3d 错误 CS0246:找不到类型或命名空间名称“ParticleEmitter”
- javascript - 如何在反应中通过onChange更改图标
- xcode - 找不到 CoreData 生成的“类定义”
- visual-studio-code - 问题理解用于代码完成的 VSCode 扩展
- json - 如何映射 JSONObject - JSONObject [“id”] 未找到
- unity3d - 从给定点和角度找到矢量幅度的最便宜方法
- python-3.x - 我无法使用条目小部件中的文本
- php - 无法对与 Doctrine 的一对多关联进行排序
- asp.net-core - swagger : 无法加载 API 定义 undefined /swagger/v1/swagger.json
- html - {xml_nodeset (0)} 尝试重现网页抓取示例时出现问题(不要认为这是 JS 问题)