单击链接/按钮导航到其他路线时,ClickAwayListener 不会触发

kun*_*uan 7 javascript reactjs material-ui use-effect

我将 Material-UI ClickAwayListener 组件与使用反应路由器的现有代码一起使用。该按钮位于 的外部<ClickAwayListener> ... </ClickAwayListener>,因此我预计onClickAway在导航到其他路线之前会触发该按钮。但它没有

下面是我的代码的复制,在某种程度上证明了我的意思

function Component(){

  const handleClickAway = () => {
    // Do something here
  }

  return (
  <>
    <button>
      <Link to="/other-route">Click here </Link>
    </button>
    // Some other element here
    <ClickAwayListener onClickAway={handleClickAway}>
      <div>
        // Content
      </div>
    </ClickAwayListener>
  </>
  )
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我单击外部的任何位置并被<ClickAwayListener>触发<button>,handleClickAway但如果我单击包含<button>与其他路线类似的位置,则不会。

我尝试查看源代码,我相信ClickAwayListener这部分负责检测点击

 React.useEffect(() => {
    if (mouseEvent !== false) {
      const mappedMouseEvent = mapEventPropToEvent(mouseEvent);
      const doc = ownerDocument(nodeRef.current);

      doc.addEventListener(mappedMouseEvent, handleClickAway);

      return () => {
        doc.removeEventListener(mappedMouseEvent, handleClickAway);
      };
    }

    return undefined;
  }, [handleClickAway, mouseEvent]);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

据我所知,这部分将首先在组件安装/重新渲染时添加一个事件侦听器来单击事件,并在组件卸载之前删除该侦听器(默认行为)useEffect()。但如果是这种情况,那么在组件被任何涉及在 区域之外单击的事件卸载之前ClickAwayListener,onClickAway应该触发侦听器,因为侦听器仍然附加到单击事件。

简而言之,这是我期望的行为:

单击按钮 -->onClickAway触发 --> 组件卸载 --> 转到新路由 --> useEffect() 运行的清理代码 --> 监听器被删除

但这是迄今为止发生的事情

单击按钮 --> 组件卸载 --> 转到新路由 --> useEffect() 运行的清理代码 --> 监听器被删除

有人可以帮我解释为什么会发生这种情况吗?

小智 9

在Tejogol 链接的问题中,评论者建议在组件上使用这些道具ClickAwayListener,因为它允许组件在链接开始之前捕获触摸事件。

<ClickAwayListener mouseEvent="onMouseDown" touchEvent="onTouchStart">
Run Code Online (Sandbox Code Playgroud)

我和你遇到了同样的问题,这对我有用!这也是侵入性最小的,因为我不想弄乱我的react-router-dom代码。


Nea*_*arl 4

ClickAwayListener组件的工作原理是将事件侦听器附加到document,当鼠标事件触发时,onClickAway仅当鼠标事件不在元素内部时才会触发。

该Link组件react-router-dom本质上呈现如下所示的内容:

<a onClick={() => navigate()}>click</a>
Run Code Online (Sandbox Code Playgroud)

当您单击链接并调用 时navigate(),React 会卸载当前组件并在下一框架中安装下一个页面组件。但问题是,document处理程序仅在下一次重新渲染后进行处理,此时,事件处理程序自ClickAwayListener卸载以来已被删除,因此不会调用任何内容。

这个问题可以通过等到下一次重新渲染之后处理程序被document调用来解决。

<button
  onClick={() => {
    setTimeout(() => {
      history.push("/2");
    });
  }}
>
Run Code Online (Sandbox Code Playgroud)

现场演示

编辑 64531264/clickawaylistener-单击链接按钮导航到其他内容时不会触发