React Router Link 正在重新加载页面:与外部事件冲突

React Router Link reloading page : Conflict with external event

我正在使用 React Router 的 Link 组件来处理我应用程序中的页面转换。

我的应用包含在一个外部网页中,该网页有一些脚本(即 Google 标签管理器)在文档级别定义 link 上的事件。

这会导致与 Link 事件发生冲突:单击 link 时页面总是重新加载。

我试图通过 onClick 回调停止我的 Link 组件的传播,但没有成功: <Link onClick={(e) => { e.stopPropagation(); }} [...]>...</Link>

我看到 Link 事件也定义在 文档 级别,所以我不知道如何停止外部事件。

关于这个有什么线索吗?

谢谢!

更新: 似乎没有简单的方法可以做到这一点而不在 iframe.

中渲染整个应用程序

如果您不介意这样做,那很简单(摘自 ):

const Frame = ({ children }) => {
    const [ref, setRef] = useState(null)
    const mountNode = ref?.contentWindow.document.body

    return (
        <iframe title="iframe" ref={setRef}>
            {mountNode && ReactDOM.createPortal(children, mountNode)}
        </iframe>
    )
}

然后,将您的主应用包装为 Frame 组件的子应用。 iframe 内的点击不会冒泡到父级 window,详见 Capture click on div surrounding an iframe

这里 CodeSandbox demo 展示了这种方法。


原始(non-functioning)答案如下

在您的 AppRouter 组件上:

const blockClicks = useCallback((e) => {
    const { target } = e
    const { nodeName, href } = target
    if (
        target.closest('#root-id') &&
        nodeName === 'A' &&
        href &&
        (/^https?:\/\//.test(!href) ||
        href.startsWith(window.location.origin)
    )) {
        // amend logic specific to your use case
        // - we want to avoid blocking irrelevant clicks
        e.stopPropagation()
    }
})

useEffect(() => {
    document.addEventListener('click', blockClicks, true)

    return () =>
        document.removeEventListener('click', blockClicks, true)
})

我在我的一个应用程序中遇到了非常相似的问题,我认为解决方案是尽可能避免使用 react-router <Link /> component

我没有使用 <Link /> 组件,而是使用 react-router 提供的 withRouter() HOC :

你写了什么:

Class MyComponent extends React.Component{
  <Link onClick={(e) => { e.stopPropagation(); }} [...]>
    ...
  </Link>
}

export default MyComponent;

可以替换为:

Class MyComponent extends React.Component{

  navigate = (event, location) => {
    event.preventDefault();
    this.props.history.push(location);
  }

  <a onClick={(e, href) => { this.navigate(e, href) }} [...]>
    ...
  </a>
}

export default withRouter(MyComponent);

这应该可以防止您的 link 在文档级别捕获其他事件并获得与 <Link /> 组件相同的结果。