【问题标题】:React - `createPortal` with `document.body` causes click event to fire immediatelyReact - 带有 `document.body` 的`createPortal` 导致点击事件立即触发
【发布时间】:2021-01-21 08:16:36
【问题描述】:

我的应用有一个名为 Open Modal 的按钮。单击此按钮时,使用createPortal 将模式附加到document.body。 Link to demo

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

为此,我使用useEffect 挂钩将点击事件绑定到document 对象,如果isOpen === true:

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

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

  }, [isOpen]);

当用户第一次点击“打开模态”时,isOpen 会从false 变为true,这会导致组件重新渲染。重新渲染完成后,注册上述效果中的点击事件。

问题

第一次单击“打开模式”会导致document 的单击事件触发(您可以在控制台中看到事件处理程序的输出)。这对我来说没有意义 - document 上的点击事件怎么可能在第一次“打开模式”点击传播到它时已经注册? p>

预期行为

第一次点击“打开模式”应该只会导致document的点击事件被注册,此时事件本身不应触发。

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

如果我将模式挂载到应用根目录的同级而不是 document.body,该应用也可以正常工作(参见演示的第 39 行)。所以上述问题只有在createPortal与document.body作为容器的情况下才会出现,但我不明白为什么。

【问题讨论】:

    标签: reactjs react-hooks event-handling event-propagation react-portal


    【解决方案1】:

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

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

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

    演示链接here

    【讨论】:

    • 谢谢@Naren。这很可能是原因,尽管我无法完全理解正在发生的事情,希望有人能对此有所了解。为什么使用createPortal 似乎“减慢”传播?特别是如果在渲染完成后正在注册事件?没有createPortal,应用程序按预期工作。
    • 这个post 提供了一些关于为什么将createPortal 与document.body 一起使用是一个坏主意的见解。不过,我对原生事件和合成事件的了解还不够,无法解释我帖子中的行为。
    • 将模式附加到应用根目录的同级而不是 document.body 有效 - see line 39。
    • 你查了吗this
    • 是的,在尝试使用 createPortal 之前,我已经阅读了该内容。如果您查看我上一条评论中的演示,您会看到我正在使用他们将模式附加到应用程序根目录的兄弟 div 而不是 document.body 本身(第 39 行)的想法 - 这使得一切工作预期的。但我仍然不确定为什么使用 createPortal with document.body 会破坏传播。
    猜你喜欢
    • 2013-11-07
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2019-06-15
    相关资源
    最近更新 更多