According to this guide (https://github.com/ReactTraining/react-router/blob/master/docs/API.md#setrouteleavehookroute-hook), beforeUnload event is listened to. However, that's not the case with default browserHistory, and you need to add an enhancer as explained here (https://github.com/ReactTraining/react-router/blob/master/docs/guides/Histories.md#customize-your-history-further).
This took me a longer than necessary to track down, so perhaps references to this (https://github.com/ReactTraining/react-router/blob/master/docs/guides/Histories.md#customize-your-history-further) should be added here (https://github.com/ReactTraining/react-router/blob/master/docs/API.md#setrouteleavehookroute-hook) and here (https://github.com/ReactTraining/react-router/blob/master/docs/guides/ConfirmingNavigation.md)?
onbeforeunload
is gone from most browsers anyways: https://github.com/mjackson/history/issues/299
The custom message may be gone from most browsers, but a generic prompt is still in place. IMO this should still be supported by react-router. But even if not, shouldn't that be explained in docs somewhere?
I agree with @alexyaseen. It took me some time to find out to find out why the browser onbeforeload
hook was not used. Especially because the previous library did provide a mechanism for that (and you find that one via Google).
But most importantly. I don't see why this isn't supported at the library level. Now everybody needs to hack something themselves.
I created the following higher order function that can be used to decorate the default createHistory
method. The location
is set to null
on hard navigation.
function useBeforeUnload(createHistory) {
return (options) => {
const history = createHistory(options);
const pendingPrompts = [];
window.addEventListener('beforeunload', (e) => {
const activePrompts = pendingPrompts
.map(prompt => typeof prompt === 'function' ? prompt(null, undefined) : prompt)
.filter(message => message !== true);
if (activePrompts.length === 0) {
return undefined;
}
const message = activePrompts[0];
e.preventDefault();
e.returnValue = message;
return message;
});
const originalBlock = history.block;
history.block = (prompt) => {
pendingPrompts.push(prompt);
const unblock = originalBlock(prompt);
return () => {
pendingPrompts.pop();
return unblock();
};
};
return history;
};
}
Most helpful comment
The custom message may be gone from most browsers, but a generic prompt is still in place. IMO this should still be supported by react-router. But even if not, shouldn't that be explained in docs somewhere?