Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Component `mounted` fires twice on page load

I have a very weird error where on page load a components mounted and beforeMount fire/run twice? Each of my components represents a page, so when I load the page on mywebsite.com/contact the Contact.vue functions mounted and beforeMount fire/run twice but if I load the page on mywebsite.com/foo the Contact.vue functions mounted and beforeMount fire/run once (which is what I think? should happen).

Any idea why these functions would execute twice? I have a bit of finicky setup but it work nicely for dynamic templates.

router/index.js:

const router = new Router({
routes: [
  {
      path: (window.SETTINGS.ROOT || '') + '/:slug',
      name: 'Page',
      component: Page,
      props: true
  },
]
})

Page.vue:

<template>
  <component v-if="wp" :is="templateComponent" v-bind:wp="wp"></component>
  <p v-else>Loading...</p>
</template>

<script type="text/javascript">

import { mapGetters } from 'vuex'
import * as Templates from './templates'

// Map templates
let templateCmps = {}
_.each(Templates, cmp => {
  templateCmps[cmp.name] = cmp
})

export default {

props: ["slug"],

components: {
  ...templateCmps

  // Example:
  // 'default': Templates.Default,
  // 'contact': Templates.Contact,
  // 'home': Templates.Home,
},

computed: {
  ...mapGetters(['pageBySlug']),

  wp() {
    return this.pageBySlug(this.slug);
  },

  templateComponent() {
    let template = 'default' // assign default template

    if (!_.isNull(this.wp.template) && this.wp.template.length)
      template = this.wp.template.replace('.php','').toLowerCase()

    return template
  }
},

created() {
  this.$store.dispatch('getPageBySlug', { slug: this.slug })
}
}
</script>

Contact.vue:

<template>
    <main></main>
</template>

<script type="text/javascript">


export default {

    name: 'contact',

    mounted() {
      console.log('Contact::mounted') // this outputs twice
    },

    beforeMount() {
      console.log('Contact::beforeMount') // this outputs twice
    }
}

</script>
like image 773
sazr Avatar asked Apr 26 '18 15:04

sazr


Video Answer


1 Answers

I had (have) a similar issue. I'm not 100% sure about this, but I think the issue may be caused by vuex. Vuex has it's own internal instance of Vue (created here in the resetStoreVM() function called in the constructor()). My suspicion is that this internal instance of Vue causes some components to be re-created, which in turn triggers the lifecycle events for those components to fire more than once.

If not in vuex, is it possible that you're creating more than one instance of Vue (i.e. new Vue({})) in your app? Alternatively, is there some code that is causing your primary Vue instance or the Contact component to be initialized more than once? That's all I can think of that might cause this.

like image 175
morphatic Avatar answered Nov 24 '22 05:11

morphatic