The beforeunload event
beforeunload is an event that fires before the current page is unloaded from the browser's memory. It happens when the user closes the tab or window, reloads the page, or follows a link or types a new URL.
Theory
TL;DR
- Listened for on
window, it fires before the page is unloaded. event.preventDefault()together withevent.returnValue = ''shows the standard leave confirmation dialog.- You cannot set your own dialog text, browsers ignore it.
- Show the dialog only when there really are unsaved changes.
- Asynchronous work (
fetch, timers) does not finish here; a synchronouslocalStoragewrite does. beforeunloadcan be cancelled,unloadcan no longer be.
Quick example
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
event.returnValue = ''; // required!
});After that the browser shows a leave confirmation dialog:
Do you really want to leave this page? The data you entered may be lost.
Important:
- Modern browsers do not let you set your own text in that window. It used to be possible to write
event.returnValue = 'Are you sure?', but it is ignored now. - This was done for security and UX, so that sites cannot pressure the user with messages such as "stay with us".
When to use it
Use it when the user may lose unsaved changes, for example when they:
- are editing text but have not pressed "Save";
- are filling in a form;
- are writing a comment;
- are doing something in an app with unsaved state.
let formChanged = false;
document.querySelector('form').addEventListener('input', () => {
formChanged = true;
});
window.addEventListener('beforeunload', (e) => {
if (formChanged) {
e.preventDefault();
e.returnValue = '';
}
});Now, if the user has changed the form and tries to leave, a warning appears.
A quiet hook before leaving, without a dialog
If you only need to run cleanup or some logic before unloading, with no dialog:
window.addEventListener('beforeunload', () => {
localStorage.setItem('lastVisited', new Date().toISOString());
});This event is the last point where data can be saved to localStorage or sessionStorage.
The difference between beforeunload and unload
| Event | When it fires | Can it stop the exit | When to use it |
|---|---|---|---|
beforeunload | Before unloading | Yes, via preventDefault() | Warning about unsaved data |
unload | After unloading has started | No | Cleanup, analytics, logging |
Limitations
- You cannot use
alert()orconfirm()insidebeforeunload, browsers block them. - Do not start asynchronous operations (requests,
fetch), they will not finish. For analytics there isnavigator.sendBeacon(). - It works only in a browser window or tab, not in frames.
- Better not to attach it without a reason, it is UX spam. Many browsers will not show the dialog at all if the user has not interacted with the page yet.
Summary
| What it does | The beforeunload event |
|---|---|
| When it fires | Before the user leaves the page |
| What it is for | Warning about the loss of unsaved data |
| How to stop the exit | event.preventDefault() plus event.returnValue = '' |
| Custom text | Not possible, the browser shows its standard one |
| When it does not fit | Asynchronous work, it will not have time to run |
An easy way to remember:
beforeunloadis the "last chance" to tell the browser: "Stop! The user has unsaved data."
Common mistakes
- Attaching the handler unconditionally. A dialog on every exit is annoying and protects nothing. Keep an "unsaved changes" flag and check it inside the handler.
- Forgetting
event.returnValue = ''. In some browserspreventDefault()alone is not enough and the dialog simply never appears. - Counting on custom text. A string returned from the handler or assigned to
returnValueis not displayed anywhere any more. - Sending analytics with
fetch. The request is torn down with the page. That is whatnavigator.sendBeacon()exists for, and the browser delivers it after the unload. - Not removing the handler after saving. After a successful
submityou have to reset the flag or callremoveEventListener, otherwise the user sees the warning even though the data is already saved. - Relying on
unload. It is not guaranteed to fire on mobile and it breaks the bfcache, so back and forward caching stops working. To persist state, listening tovisibilitychangewith thehiddenstate is more reliable.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.