Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
Javascript 如何在使用ReactDOM.createPortal()的子级上处理ref.current.contains()?_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 如何在使用ReactDOM.createPortal()的子级上处理ref.current.contains()?

Javascript 如何在使用ReactDOM.createPortal()的子级上处理ref.current.contains()?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我使用React钩子创建了一个应用程序。我有一个助手函数onClickOutsideHook(ref,callback),当您使用React在提供ref的组件外部单击时,它会触发回调 export const onClickOutsideHook=(ref,callback)=>{ //钩住https://stackoverflow.com/a/42234988/8583669 React.useffect(()=>{ const handleClickOutside=事件=>{ if(ref?

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

export const onClickOutsideHook=(ref,callback)=>{
//钩住https://stackoverflow.com/a/42234988/8583669
React.useffect(()=>{
const handleClickOutside=事件=>{
if(ref?current&!ref.current.contains(event.target)){
回调();
}
};
//绑定事件侦听器
文件。添加了文本列表(“鼠标向下”,手动单击外部);
return()=>{
//在清理时取消绑定事件侦听器
文档。移除EventListener(“鼠标向下”,把手单击外部);
};
},[callback,ref]);
};
我有一个组件
下拉列表
,它使用此帮助器,因此当您在其外部单击时,它将关闭。此组件有一个
Modal
组件作为使用
ReactDOM.createPortal
的子组件。我用它来渲染
主体中的
模式
,这样它就可以覆盖所有的应用程序屏幕。My
Modal
包含一个按钮,当您单击该按钮时,该按钮会提示消息:

函数模态(){
返回ReactDOM.createPortal(
警报(“单击模式”)}>单击
,
文件正文
);
}
功能下拉列表(道具){
const[isModalOpen,setIsModalOpen]=React.useState(false);
const dropdownRef=React.useRef(null);
onclick外侧钩(dropdownRef,props.onClose);
返回(
单击外部,我将关闭
setIsModalOpen(真)}>打开模式
{isModalOpen?:}
);
}
问题是,当我单击
模式
按钮触发警报时,
下拉列表
在之前关闭,因为我在其外部单击(
模式
不是作为
下拉列表
的子项呈现,而是在
正文
中)。所以我的警报永远不会被触发

是否有一种方法可以使用
ref
Modal
定义为
下拉列表的子项
,但仍然使用
ReactDOM.createPortal
正文中呈现它


只需查看。

作为一种解决方法,您可以在模态中添加ID属性,然后检查单击是否在模态之外

function Modal() {
  return ReactDOM.createPortal(
    <div id="modalId">
      <button onClick={() => alert("Clicked on Modal")}>Click</button>
    </div>,
    document.body
  );
}
就像医生说的:

尽管门户可以位于DOM树中的任何位置,但它在其他方面的行为都类似于普通的React子级

这包括事件冒泡。从门户内部激发的事件将 传播到树中的祖先,即使 元素不是DOM树中的祖先

但情况并非如此,在文档中添加了mousedown事件侦听器,而不仅仅是下拉列表组件。即便如此,泡沫仍在发生

这意味着,如果将ref添加到模式,然后在mousedown事件上添加事件侦听器以停止传播,则永远不会调用handleClickOutside函数

这似乎仍然是一个解决办法,我不知道是否有一个适当的方法来检查

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
  );
}
函数模态(){
const modalRef=useRef();
useffect(()=>{
常数stopPropagation=e=>{
e、 停止传播();
};
const{current:modalDom}=modalRef;
modalDom.addEventListener(“鼠标向下”,停止播放);
return()=>{
modalDom.removeEventListener(“鼠标下移”,停止播放);
};
}, []);
返回ReactDOM.createPortal(
警报(“单击模式”)}>单击
,
文件正文
);
}

观看下面的模态组件。

嘿,谢谢你的想法,但正如你所说的,这只是一个解决办法;)向上投票感谢您的帮助它工作得非常完美,这是一个很好的解决方法,因为它只会影响
Modal
组件
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
  );
}