Search code examples
vue.jsevent-listenerremoveeventlistener

Vue: beforeunload event listener is not being removed


I'm working on an undo delete functionality, it consist of a small modal which allows the user to undo/delay the action for a limited amount of time(similar to gmail). However, I want to ensure that the action is executed if the user decides to navigate to another window or close the tab, which I am doing like so:

mounted() {
  this.timeout = setTimeout(() => {
    this.close(true);
  }, this.duration);
  window.addEventListener('beforeunload', this.forceDestroyHandler, { capture: true });
},
methods: {
  close(deleteBeforeClosing) {
    if (deleteBeforeClosing) {
      clearTimeout(this.timeout);
      // This is the function dispatching to the store and deleting the item
      this.destructiveEvent(this.category, this.item.id);
    }
    this.$emit('close');
}

I am then (attempting) to remove the event listener on beforeDestroy:

beforeDestroy() {
  this.forceDestroy();
  window.removeEventListener('beforeunload', this.forceDestroyHandler, {capture: true});
},

However, it appears that beforeDestroy is never called, meaning the event listener is never removed - so if the user decides the close the tab or navigate, he is prompted a message even tough the undo component is not even showing anymore. If the user would click on cancel, another action would be dispatched to the store attempting to delete an already deleted item causing an server error.

I also tried to put the removeEventListener elsewhere but I am keep having the same issue.


Solution

  • To further elabourate on my comment: the reason why your onbeforeunload event listener is not unbound is because the beforeDestroy() lifecycle hook is only fired when a VueJS component is destroyed. When you close the browser tab/window, the entire thread is wiped and this does not trigger component destruction.

    Since you only want to remove the listener after the modal is closed, it makes sense to do it in the close() method: hence why you approach worked.