React-具有document.body的createPortal导致click事件立即触发 [英] React - `createPortal` with `document.body` causes click event to fire immediately

查看:67
本文介绍了React-具有document.body的createPortal导致click事件立即触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序有一个名为 Open Modal 的按钮.单击此按钮后,将使用 createPortal 将模态附加到 document.body . 链接至演示

My app has a button called Open Modal. When this button is clicked, a modal is appended to the document.body using createPortal. Link to demo

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

Once the modal has been mounted (i.e. isOpen === true), I would like to print some text to the console each time the user clicks somewhere on the page.

要执行此操作,如果 isOpen === true ,我将使用 useEffect 挂钩将click事件绑定到 document 对象:

To do this, I'm using a useEffect hook to bind a click event to the document object if isOpen === true:

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

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

  }, [isOpen]);

当用户第一次单击打开模式"时, isOpen false 更改为 true ,这将导致组件重新显示-使成为.重新渲染完成后,将注册具有上述效果的click事件.

When the user clicks 'Open Modal' for the first time, isOpen changes from false to true, this causes the component to re-render. Once the re-render is complete, the click event in the above effect is registered.

问题

第一次单击打开模式"会触发 document 的click事件(您可以在控制台中看到事件处理程序的输出).这对我来说没有任何意义-在第一次打开模式"点击传播到此之前,文档上的click事件如何可能已经注册?/strong>

Clicking 'Open Modal' for the first time causes the document's click event to fire (you can see the event handler's output in the console). This doesn't make sense to me - how is it possible for the click event on document to already be registered by the time the first 'Open Modal' click has propagated up to it?

预期行为

第一次点击打开模式"应该只导致注册 document 的click事件,此时该事件本身不应该触发.

The first click on 'Open Modal' should only result in the document's click event being registered, the event itself should not fire at this point.

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

If I omit createPortal (see line 38 of the demo), the app works as expected, i.e. the event is registered on the first click on 'Open Modal' and the event handler is called on all subsequent clicks on the page.

如果我将模式安装到应用程序根目录的同级而不是 document.body 上,则该应用程序也将按预期运行(请参见演示的第39行).因此,上述问题仅在 createPortal document.body 作为容器一起使用时发生,但我不明白为什么.

The app also works as expected if I mount the modal to a sibling of the app root instead of document.body (see line 39 of the demo). So the problem described above only occurs when createPortal is used with document.body as the container, but I don't understand why.

推荐答案

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

I'm not sure exactly, But I think, the problem occurring because of Event Propagation, By the time propagation completes, document click event is been registered, that might be reason it's calling the eventHandler. Correct me if am I'm wrong.

如果您停止事件传播,就可以正常工作.

If you stop the event propagation, it's working fine.

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

演示链接这里

这篇关于React-具有document.body的createPortal导致click事件立即触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆