The snippet below is suppose to add and remove event listener handleBeforeUnload. On checking the browser console I see the "inside else" getting printed however loading the page still throws the alert.
Any ideas why the event listener might not be getting removed?
useEffect(() => {
const handleBeforeUnload = (e) => {
e.preventDefault();
const message =
'Are you sure you want to leave? All provided data will be lost.';
e.returnValue = message;
return message;
};
if (condition1 && condition2) {
console.log('inside if');
window.addEventListener('beforeunload', handleBeforeUnload);
} else {
console.log('inside else');
window.removeEventListener('beforeunload', handleBeforeUnload);
}
}, [stateVariable1, stateVariable2, stateVariable3]);
Additionally, is there any alternative to detecting a reload other than using beforeunload event? Since the returnValue property is deprecated the default message is really unhelpful. How can one detect and create custom alert messages?
I still see the popup even when the console prints the else statement, which means ideally the event listener ought to have been removed.
It's because the event listener function
handleBeforeUnloadis defined inside the effect. So when the effect runs again to remove it, thehandleBeforeUnloadfunction is re-created and this is not referentially equivalent to the one that was being used when the effect ran to register the event listener.To fix this you need to return a cleanup function from the effect. The cleanup function that is returned will be executed by react just before the next effect execution runs. Since that closure has a reference to the exact (referentially the same)
handleBeforeUnloadthat was used to register it from that effect execution, it will work.When the condition evaluates to false, the cleanup function for the previously registered handler will be removed, and a new one wont be registered since its guarded by that condition.
No there is not. It's very purposefully limited because blocking the user from leaving has to be tightly controlled in the web standards, as it could be abused.