Search code examples
javascriptvue.jselectronvue-routervue-cli

Switching between Vue Router pages cause multiple event fire on VueJS mounted()


I am working on an Electron project where I use Vue CLI project and the Vue CLI Plugin Electron Builder. Everything works great except a weird bug that I found recently.

Whenever I navigate between pages (Vue Router), the event I listen for from the component mounted() property becomes double. It's actually the N+1 issue.

to describe the issue more clearly, I have two Home.vue and HelloWorld.vue components. From Home.vue component, I am sending an event to the main process whenever clicking a button and listening the event.reply() from the same component mounted() property. It's completely as expected at this stage.

However, whenever I go to the HelloWorld page and switch back to the Home page again and when I click the button to send and receive the event from the main process, I don't only see a single event even though I click one time only but I see two event reply. If I switch between pages again, I'll see three event reply and so on like N+1 issue.

For your convenience, I made a quick GIF that will show the issue clearly.

sending and receiving event from the Electron main process

Home.vue

<template>
  <div class="home">
    <button @click="send()">Home</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  data() {
    return {
      cause: null
    }
  },
  mounted() {
    window.ipcRenderer.on("home:reply", event => console.log(event));
  },
  methods: {
    send() {
      window.ipcRenderer.send("home");
    }
  },
};
</script>

main.js

ipcMain.on("home", event => {
  return event.reply("home:reply");
});

I don't have anything special on the Vue Router and it's just default scaffolding that comes with the Vue CLI. As you can see in the above code snippet, all I am doing is just sending an event when clicking a button and listening for the same event reply from the same component mounted() property.

I also found a similar topic on Stack Overflow but couldn't figure it out myself. I have no clue what's wrong on my code 🥱


Solution

  • You need to unregister the event handler when the component is destroyed, otherwise you'll just keep registering the same event handler again and again each time the component is mounted.

    mounted() {
      window.ipcRenderer.on('home:reply', this.handleHomeReply)
    },
    
    destroyed() {
      window.ipcRenderer.off('home:reply', this.handleHomeReply)
    },
    
    methods: {
      handleHomeReply(event) {
        console.log(event)
      }
    }