在 Next JS 中检测用户何时离开页面

Mad*_*eka 17 next.js

我想检测用户何时离开页面 Next JS。我统计了 3 种离开页面的方式:

  1. 通过点击链接
  2. 通过执行触发 router.back、router.push 等的操作...
  3. 通过关闭选项卡(即当 beforeunload 事件被触发时

能够检测页面何时离开非常有用,例如,提醒用户某些更改尚未保存。

我想要这样的东西:

router.beforeLeavingPage(() => {
    // my callback
})
Run Code Online (Sandbox Code Playgroud)

Lui*_*eno 19

我使用像Next.js 页面一样的“next/router”来断开套接字

import { useEffect } from "react";
import { useRouter } from "next/router";

export default function MyPage() {
  const router = useRouter();

  useEffect(() => {
    const exitingFunction = () => {
      console.log("exiting...");
    };

    router.events.on("routeChangeStart", exitingFunction);

    return () => {
      console.log("unmounting component...");
      router.events.off("routeChangeStart", exitingFunction);
    };
  }, []);

  return <>My Page</>;
}
Run Code Online (Sandbox Code Playgroud)


Bry*_*eld 8

router.beforePopState非常适合浏览器后退按钮,但不适用于<Link>页面上的 s。

在这里找到解决方案: https: //github.com/vercel/next.js/issues/2694#issuecomment-732990201

...这是采用这种方法的版本,供任何进入此页面寻找其他解决方案的人使用。请注意,我已根据我的要求对其进行了进一步调整。

// prompt the user if they try and leave with unsaved changes  
useEffect(() => {
  const warningText =
    'You have unsaved changes - are you sure you wish to leave this page?';
  const handleWindowClose = (e: BeforeUnloadEvent) => {
    if (!unsavedChanges) return;
    e.preventDefault();
    return (e.returnValue = warningText);
  };
  const handleBrowseAway = () => {
    if (!unsavedChanges) return;
    if (window.confirm(warningText)) return;
    router.events.emit('routeChangeError');
    throw 'routeChange aborted.';
  };
  window.addEventListener('beforeunload', handleWindowClose);
  router.events.on('routeChangeStart', handleBrowseAway);
  return () => {
    window.removeEventListener('beforeunload', handleWindowClose);
    router.events.off('routeChangeStart', handleBrowseAway);
  };
}, [unsavedChanges]);
Run Code Online (Sandbox Code Playgroud)

到目前为止,它似乎工作得相当可靠。

或者,您可以自己添加一个onClick到所有<Link>s 中。


use*_*488 7

浏览器严格限制权限和功能,但这有效:

  • window.confirm:用于 next.js 路由器事件
  • beforeunload:用于浏览器重新加载、关闭选项卡或导航离开
import { useRouter } from 'next/router'

const MyComponent = () => {
  const router = useRouter()
  const unsavedChanges = true
  const warningText =
    'You have unsaved changes - are you sure you wish to leave this page?'

  useEffect(() => {
    const handleWindowClose = (e) => {
      if (!unsavedChanges) return
      e.preventDefault()
      return (e.returnValue = warningText)
    }
    const handleBrowseAway = () => {
      if (!unsavedChanges) return
      if (window.confirm(warningText)) return
      router.events.emit('routeChangeError')
      throw 'routeChange aborted.'
    }
    window.addEventListener('beforeunload', handleWindowClose)
    router.events.on('routeChangeStart', handleBrowseAway)
    return () => {
      window.removeEventListener('beforeunload', handleWindowClose)
      router.events.off('routeChangeStart', handleBrowseAway)
    }
  }, [unsavedChanges])

}
export default MyComponent
Run Code Online (Sandbox Code Playgroud)

归功于这篇文章


Dar*_*ert 3

您可以在 React 页面或组件中使用默认Web api 的事件处理程序。

if (process.browser) {
  window.onbeforeunload = () => {
    // your callback
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么您需要检查“process.browser”,以确保下面的代码仅在客户端有效。 (3认同)