Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React-`createPortal`和`document.body`一起导致立即触发click事件_Reactjs_React Hooks_Event Handling_Event Propagation_React Portal - Fatal编程技术网

Reactjs React-`createPortal`和`document.body`一起导致立即触发click事件

Reactjs React-`createPortal`和`document.body`一起导致立即触发click事件,reactjs,react-hooks,event-handling,event-propagation,react-portal,Reactjs,React Hooks,Event Handling,Event Propagation,React Portal,我的应用程序有一个名为“打开模式”的按钮。单击此按钮时,将使用createPortal将模式附加到文档.body 一旦安装了模式(即,isOpen===true),每次用户单击页面上的某个位置时,我都会向控制台打印一些文本 为此,如果isOpen===true,我将使用useffect钩子将单击事件绑定到document对象: useEffect(() => { const eventHandler = () => console.log("You clicked

我的应用程序有一个名为“打开模式”的按钮。单击此按钮时,将使用
createPortal
将模式附加到
文档.body

一旦安装了模式(即,
isOpen===true
),每次用户单击页面上的某个位置时,我都会向控制台打印一些文本

为此,如果
isOpen===true
,我将使用
useffect
钩子将单击事件绑定到
document
对象:

useEffect(() => {
    const eventHandler = () => console.log("You clicked me");

    if (isOpen) {
      document.addEventListener("click", eventHandler);
    }

  }, [isOpen]);
当用户第一次单击“打开模式”时,
isOpen
false
更改为
true
,这会导致组件重新渲染。重新渲染完成后,将注册上述效果中的单击事件

问题

第一次单击“打开模式”会触发
文档的单击事件(您可以在控制台中看到事件处理程序的输出)。这对我来说毫无意义-当第一次“打开模式”点击传播到文档上时,
文档上的点击事件如何可能已经注册?

预期行为

第一次单击“打开模式”只会导致注册
文档
的单击事件,此时不应触发事件本身

如果我省略了
createPortal
(请参见演示的第38行),应用程序将按预期工作,即在第一次单击“打开模式”时注册事件,并在页面上所有后续单击时调用事件处理程序


如果我将modal挂载到应用程序根目录的同级,而不是
document.body
(请参见演示的第39行),那么应用程序也可以正常工作。因此,上述问题仅在
createPortal
document.body
一起用作容器时才会出现,但我不明白原因。

我不确定确切原因,但我认为,在传播完成时,由于
事件传播而出现的问题,文档
click
事件已注册,这可能是它调用
eventHandler
的原因。如果我错了,请纠正我

如果停止事件传播,它工作正常

const openModal = useCallback(
    function (e) {
      if (!isOpen) { // stopping the propagation
        e.stopPropagation();
      }
      setOpen(true);
    },
    [setOpen, isOpen]
  );

演示链接

谢谢@Naren。这很可能就是原因,尽管我不能完全理解到底发生了什么,希望有人能对此有更多的了解。为什么使用
createPortal
似乎会“减慢”传播?尤其是在渲染完成后注册事件时?在没有
createPortal
的情况下,该应用程序可以正常工作。这提供了一些见解,说明了为什么将
createPortal
document.body
一起使用是个坏主意。不过,我对本机事件和合成事件的了解还不够,无法解释我文章中的行为。将模式附加到应用程序根目录的同级,而不是
document.body
works-。您是否选中了“是”,我在尝试使用
createPortal
之前已经阅读过。如果您查看我上一篇评论中的演示,您将看到我在使用他们的想法,将模态附加到应用程序根目录的兄弟div,而不是
document.body
本身(第39行)-这使一切都按预期工作。但我仍然不确定为什么将
createPortal
document.body
一起使用会扰乱传播。