https://codesandbox.io/s/wn7j570y85
Simply click on button named "Mounted triggered twice, see console" and see in console.
(reproducable only with css:false for transition)
mounted once
mounted twice
The bug is still present on last release 2.7.1
It can be fixed quickly ? it's really a brake on client-side performance.
(Related : https://github.com/nuxt/nuxt.js/issues/5616)
I pulled this down locally and am only seeing a single mount. Maybe this is an issue with code sand box?
no, you forgot something. The next page must have an other layout and css:false for transition (navigation on client side). I have the same bug locally.
I have to make a video to prove it to you?
Someone is alive ? :)
Hi @usb248
This still happens in version 2.8.0
The problem is when transition: {css: false}
it's defined
Any core team feels concerned ?
It's not just transition, still mounts twice on this.$router.push
This still seems to be an issue when transitioning from one layout to another, could we get a re-open?
nuxt version 2.9.2
Happening with Nuxt version 2.10.0 as well. I am using nuxt generate. It only happens in the production build.
@amritk @swapneelvivekdesaithoughtworks with the same reproduction from above? If not, please provide one.
Hit the link and watch the console
https://codesandbox.io/s/nuxt-vuetify-k7yv9
Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:
Issues that are labeled as pending
will not be automatically marked as stale.
It is still an issue:
I can confirm this does still happen with Nuxt 2.10.2 when page transitions are enabled.
I used to have these objects in my Nuxt config file in order to enable transitions:
layoutTransition: {
name: 'layout',
mode: ''
},
pageTransition: {
name: 'page',
mode: ''
}
I had to remove both of them to prevent pages components to be mounted/created twice.
As a temporary fix, I wrapped my code inside mounted
in if
condition. The condition is just to check if the layout name is the one I am expecting.
if (this.$nuxt.layoutName === 'myLayout') {
...
}
Don't know if this can help, but I managed to find my problem by putting breakpoints inside the fetch methode to realize the page was being loaded twice, by two different methods.
We had an el-menu made by Element-UI, that had inside of it, nuxt-links, so the route was loaded twice simultaneously.
I realize this was a coding error but this might help anyone looking for awnsers. Try to trace how the route gets changed !
My temporary workaround.
~/plugins/inject-layout.js
export default (context, inject) => {
inject('layout', {
// Layout name and route.name of pages that are not dafault layout
map: {
'one-column': ['signup', 'signin'],
'some-other-layout': ['some-route-name']
},
// Property that represents correct layout name of current page
current: 'default'
})
}
nuxt.config.js
export default {
plugins: ['~/plugins/inject-layout.js']
}
~/mixins/layout.js
export default {
// Set and keep correct layout name of current page
layout({ app, route }) {
let layoutName = 'default'
for (const [key, value] of Object.entries(app.$layout.map)) {
if (value.includes(route.name)) layoutName = key
}
app.$layout.current = layoutName
return layoutName
},
data() {
return {
// True while duplicated lifecycle hooks are running
incorrectLayout: this.$nuxt.layoutName !== this.$layout.current
}
}
}
~/pages/*/.vue
import layout from '~/mixins/layout'
export default {
// Layout setting
mixins: [layout],
// Hooks will be executed twice, but
mounted() {
// Return immediately if duplicated runs
if (this.incorrectLayout) return
console.log('This is only displayed once.')
}
}
This is still occurring for me as of today, in [email protected]. My Vue browser extension reports that in the default layout, there are two
While running in dev mode, if I remove the
Given that this is happening within Nuxt, I don't know of any workarounds or logical statements that can prevent it.
similar to https://github.com/nuxt/nuxt.js/issues/6961
I have the same issue with twice mounted on nuxt, what I did is this.
<client-only>
<nuxt /> // On your layout
<client-only>
hope it helps.
I had something similar
the problem was in the incorrectly registered plugin
@tsarrB can you provide any details? examples?
@gerasimvol
my case is described here
That's still a huge problem, some components mounts twice - that's lead to visual bugs (for example, i have component that mount maps-script, and that leads for two maps visible).
I disabled SSR, cause site now in just demo mode, but I'll need SSR soon. Using generate mode.
Any updates?
I'm facing the same issue! Using "nuxt": "^2.11.0". Need to check layout name before firing stuff inside created hook to prevent firing twice :(
Same issue. beforeDestroy
fires twice too,and I cannot get the right this.$nuxt.layoutName
in beforeDestroy
After a few weeks studying this issue, I've found another "fix" using Vuex / Nuxt Store.
By putting a 'v-if' statement on the <nuxt/>
element on the layout itself you can prevent it from loading the content of the linked route before the layout changes.
This way you won't need to deal with every 'created' or 'mounted' function on your page components.
What I did:
Step 1) create a pages.js
store module to register the content status.
IMPORTANT: to use vuex modules like this, you need to create an index.js
file on ~/store
folder
~/store/pages.js
export const state = () => ({
showLayoutContent: true // show by default in case of first access or refreshing the page
})
export const mutations = {
TOGGLE_LAYOUT_CONTENT (state, isVisible) {
state.showLayoutContent = isVisible
},
}
Step 2) Create an app.js
middleware to hide the content on every route change
~/middleware/app.js
export default function (context) {
// hide the content
context.store.commit('pages/TOGGLE_LAYOUT_CONTENT', false)
}
Step 3 Add the middleware reference to your nuxt.config.js
to extend the router property
~/nuxt.config.js
//{...}
router: {
middleware: ['app']
},
//{...}
Step 4 Enable and use the store on your layout.
Ex: ~/layouts/dashboard.vue
<template>
{...}
<!-- Page Content -->
<nuxt v-if="showContent" />
{...}
</template>
<script>
export default {
computed: {
showContent () {
return this.$store.state.pages.showLayoutContent
},
},
beforeCreate () {
this.$store.commit('pages/TOGGLE_LAYOUT_CONTENT', true)
}
}
</script>
Extra) In my case I've used the vue extends
property for my Layout components. The ~/layouts/default.vue
layout being the base and all other layouts extending from it.
This way the computed()
and beforeCreated()
are created only once and I can reuse the showContent
computed property on the extended Layout files.
Hope it helps
same here https://github.com/nuxt/nuxt.js/issues/6961
cause serious visual issues 🙁
Will look at it, sorry for the delay 😬
Update: the issue seems to come only when doing server-side rendering (no issue with nuxt dev --spa
).
I looked at the Vue Devtools and indeed, the default layout looked different when server-rendered <Default>
vs client-side <layouts/default.vue>
(when navigating on error page for example)
SSR:
After navigating:
So it actually re-render the whole layout, causing the new mounted() hooks.
Keeping the investigation 🕵🏻♂️
I found the issue, apparently the name
of the layout is not defined, which cause a different name between server-side rendering and client-side (Default
on SSR and layouts/default.vue
on client).
As a quick workaround: Set a name for each of your layouts:
layouts/default.vue
<template>...</template>
<script>
export default {
name: 'default'
}
</script>
I will make a PR to fix it in the next patch release of NuxtJS.
Thank you very much for reporting this and sorry for this outstanding delay 😞
Fixed in V2.12.1 release 🔥
For me, it is still calls mounted twice.
@asolopovas Would you please fill in a new issue with reproduction code?
Still happens in v2.12.2
Still happens in v2.12.2
Then create a new issue and a reproduction CodeSandbox or repo 😉
@manniL why not reopen this issue? i have same issue
<template>
<div id="layout-web">
<span> <!-- there has a span,it works -->
<nuxt />
</span>
<SignDialog />
</div>
</template>
<template>
<div id="layout-web">
<nuxt /> <!-- has same level html, has bug, mounted twice -->
<SignDialog />
</div>
</template>
Same issue on 2.12.2
Yep, still happening on 2.12.2
still happening
Then create a new issue and a reproduction CodeSandbox or repo 😉
@Atinux
First of all, thanks for you effort and suggestion!
Using nuxt 2.12.2 and still have the problem
I am using both SPA and SSR
I found the issue, apparently the
name
of the layout is not defined, which cause a different name between server-side rendering and client-side (Default
on SSR andlayouts/default.vue
on client).As a quick workaround: Set a name for each of your layouts:
layouts/default.vue
<template>...</template> <script> export default { name: 'default' } </script>
I will make a PR to fix it in the next patch release of NuxtJS.
Thank you very much for reporting this and sorry for this outstanding delay 😞
tried this but have not resolved, any other suggestion :(
Hi - I am getting this error as well. I followed this pattern to create nested layout: https://constantsolutions.dk/2020/02/nested-layouts-in-nuxt-vue-js/ I am not sure if the other guys uses "slots" as well in their layout, and that's why it is happening?
As an example, in my pages/_slug.vue I have this:
mounted () {
console.log('Mounted!', this.$nuxt.layoutName, this.$nuxt);
}
And in the console I get:
The strange thing is that no matter what I set in the layout name, it will always return "page" or "default". Changing page layout name to "name: 'APage'," it will still say it mounted "page".
I believe this could be the reason why my Nuxt application is slow when changing pages, despite having an API response time of 50ms.
reopen this issue?
Hi @manniL, I wanted to make a reproducible case, so I forked @amritk's codesandbox, and updated to Nuxt version 2.12.2 - I can confirm I didn't have to make any changes for the error to appear.
It writes "I have been mounted" twice in the console, see here: https://codesandbox.io/s/nuxt-vuetify-0xz91?file=/package.json. I even tried to give a name to the layout file.
When switching to the about page:
i have been created. Layout: default
i have been mounted. Layout: default
i have been created. Layout: other
i have been mounted. Layout: other
It's also weird it calls the layout "other" when I call this.$nuxt.layoutName
, because I explicitly set the name to be otherlayout
.
I think it would be appropriate to reopen this issue. Also I believe it causes page switches to take extra long time - we just launched our production site: https://thejewelleryroom.com and when switching pages to a page that has been cached by Cloudflare, and the response time is 50-100ms, it still takes 1-2 seconds for the page to switch. Perhaps it is because it mounts the page twice?
This is a very serious bug. I cannot not generate unique id for a client side only map container because it is calculated twice. I can not push a value to my empty-by-default array because it is pushed twice.
Issue reopened here: https://github.com/nuxt/nuxt.js/issues/7441
@melihplt you can make this workaround in your mounted/created hook.
if (this.$nuxt.layoutName === 'myLayout') {
// will only fire once
}
However, it does not solve the performance issues it generates.
My temporary workaround.
~/plugins/inject-layout.js
export default (context, inject) => { inject('layout', { // Layout name and route.name of pages that are not dafault layout map: { 'one-column': ['signup', 'signin'], 'some-other-layout': ['some-route-name'] }, // Property that represents correct layout name of current page current: 'default' }) }
nuxt.config.js
export default { plugins: ['~/plugins/inject-layout.js'] }
~/mixins/layout.js
export default { // Set and keep correct layout name of current page layout({ app, route }) { let layoutName = 'default' for (const [key, value] of Object.entries(app.$layout.map)) { if (value.includes(route.name)) layoutName = key } app.$layout.current = layoutName return layoutName }, data() { return { // True while duplicated lifecycle hooks are running incorrectLayout: this.$nuxt.layoutName !== this.$layout.current } } }
~/pages/*/.vue
import layout from '~/mixins/layout' export default { // Layout setting mixins: [layout], // Hooks will be executed twice, but mounted() { // Return immediately if duplicated runs if (this.incorrectLayout) return console.log('This is only displayed once.') } }
Why so complicated... And is it sure, that you (even if really loaded twice) don't need some of the mounded code?
From my point of view this issue seems only to happen, if layout isn't default layout.
I have this issue on different pages, that use layout-property with another layout than default. If I remove layout-property from page (or set it to default), it isn't mounted twice. If you switch back to another layout, it's again mounted twice.
But in both mounts, it is mounted with the same layout-name - so you cannot say "if layout default don't mount..."
I'd just insert this into the pages mounted-function - but only on pages that don't use default layout:
mounted() {
...
if (window.mounted_componentname == true) return;
window.mounted_componentname = true;
....
}
thats ugly, but it works for me...
have same issue
same issue...
same issue
same issue
This is still happening in 2.14.7
Most helpful comment
I found the issue, apparently the
name
of the layout is not defined, which cause a different name between server-side rendering and client-side (Default
on SSR andlayouts/default.vue
on client).As a quick workaround: Set a name for each of your layouts:
layouts/default.vue
I will make a PR to fix it in the next patch release of NuxtJS.
Thank you very much for reporting this and sorry for this outstanding delay 😞