Detect when a user leaves page in Next JS
Solution 1
You can use default web api's eventhandler in your react page or component.
if (process.browser) {
window.onbeforeunload = () => {
// your callback
}
}
Solution 2
You can use router.beforePopState
check here for examples
Solution 3
this worked for me in next-router / react-FC
- add router event handler
- add onBeforeUnload event handler
- unload them when component unmounted
https://github.com/vercel/next.js/issues/2476#issuecomment-563190607
Solution 4
I saw two things when coding it :
- Knowing when nextjs router would be activated
- Knowing when specific browser event would happen
I did a hook that way. It triggers if next router is used, or if there is a classic browser event (closing tab, refreshing)
import SingletonRouter, { Router } from 'next/router';
export function usePreventUserFromErasingContent(shouldPreventLeaving) {
const stringToDisplay = 'Do you want to save before leaving the page ?';
useEffect(() => {
// Prevents tab quit / tab refresh
if (shouldPreventLeaving) {
// Adding window alert if the shop quits without saving
window.onbeforeunload = function () {
return stringToDisplay;
};
} else {
window.onbeforeunload = () => {};
}
if (shouldPreventLeaving) {
// Prevents next routing
SingletonRouter.router.change = (...args) => {
if (confirm(stringToDisplay)) {
return Router.prototype.change.apply(SingletonRouter.router, args);
} else {
return new Promise((resolve, reject) => resolve(false));
}
};
}
return () => {
delete SingletonRouter.router.change;
};
}, [shouldPreventLeaving]);
}
You just have to call your hook in the component you want to cover :
usePreventUserFromErasingContent(isThereModificationNotSaved);
This a boolean I created with useState and edit when needed. This way, it only triggers when needed.
Solution 5
router.beforePopState
is great for browser back button but not for <Link>
s on the page.
Solution found here: https://github.com/vercel/next.js/issues/2694#issuecomment-732990201
... Here is a version with this approach, for anyone who gets to this page looking for another solution. Note, I have adapted it a bit further for my requirements.
// 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]);
So far, it seems to work pretty reliably.
Alternatively you can add an onClick
to all the <Link>
s yourself.
Related videos on Youtube
Chukwu3meka
I'd say, am a Fullstack developer 👻 I've worked on Mobile, Desktop and Web development 💬 I'm also a Computer Science graduate 🎓 am currently learning Flutter and also interested in Cyber Security 📚
Updated on June 04, 2022Comments
-
Chukwu3meka almost 2 years
I would like to detect when the user leaves the page Next JS. I count 3 ways of leaving a page:
- by clicking on a link
- by doing an action that triggers router.back, router.push, etc...
- by closing the tab (i.e. when beforeunload event is fired
Being able to detect when a page is leaved is very helpful for example, alerting the user some changes have not been saved yet.
I would like something like:
router.beforeLeavingPage(() => { // my callback })
-
juliomalves about 2 yearsYou can use the
beforePopState
event to detect changes to the session history navigation as suggested in Want to have an event handler for the browser's back button with next.js. This covers both your point 1. and 2..
-
Chukwu3meka over 3 yearsI don't think that will always work, because SSR will give you undefined when you use the window object
-
Darryl RN over 3 yearsthats why you need to check
process.browser
, to make sure the code below works only in client side. -
Mr. Robot over 2 yearsThis is not an answer
-
juliomalves over 2 yearsHere's a practical example on how to use the
beforePopState
event to detect back/forward actions: Want to have an event handler for the browser's back button with next.js.