Environment
- Operating System: Darwin
- Node Version: v20.17.0
- Nuxt Version: 3.17.5
- CLI Version: 3.25.1
- Nitro Version: 2.11.12
- Package Manager: npm@11.4.1
- Builder: -
- User Config: compatibilityDate, devtools, ssr, app
- Runtime Modules: -
- Build Modules: -
Reproduction
https://stackblitz.com/github/exophunk/nuxt-doublemounted-issue
https://github.com/exophunk/nuxt-doublemounted-issue
The reproduction shows various circumstances where that issue happens. Details are described in the reproduction index page.
Steps:
- Switch between the different page examples
- See console.log() for onMounted() logging twice!
Describe the bug
Whenever you are using pageTransition or layoutTransition in your app, the usage of any async function inside the <setup> part of a page (or any child component) leads to faulty mounting the page twice!
As const { data } = await useFetch('...'); is a very common in setup, the chances of this issue to happen is quite common. Whenever you have this on combination with transitions, mounting happens twice.
-
Layout Transitions
- Using Layout Transitions:
layoutTransition: { mode: 'out-in', name: 'page', duration: 300 }
- Using any async method in setup of pages or child components
-
Page Transitions
- Using Page Transitions: pageTransition: { mode: 'out-in', name: 'page', duration: 300 }
- Using NESTED parent/child pages (for page transition, it only happens with nesting)
- Using any async method in setup of pages or child components
- Using any async method causes the issue (useFetch, useAsyncData, or any other method with await)
- Not a SSR issue, happens on client-only too
What is the problem?
Mounting a page twice (and mounting every child component twice) can lead to various unexpected bugs, especially for UI components that init themselves on mount or components that perform any idempotent actions or API calls. This can be very severe! In our case, a ecommerce checkout call was sent twice to the backend! And it was hard to spot or figure out why. Noone expects onMounted() to happen twice.
Quick fix workaround
To fix the issue, you can wrap <NuxtPage /> inside a <Suspense>.
<Suspense>
<NuxtPage />
</Suspense>
The Suspense Quick Fix seems to work fine. We have it in production now for about half a year. But I can't say if it has any drawbacks or creates issues elsewhere. It's also difficult to make sure our devs know of this workaround and do not create new pages without it.
Additional context
The issue was once further explained as a comment to #27364. The bug is open for +1 Year now.
I updated the reproduction to 3.17.5 and the bug persists.
I suggest closing the other, less clearly described issue and keep tracking this one.
If it's not an easy fix, then I would suggest that after 1 year, at least a warning in the documentation should be placed that page/layout transitions should be used with caution.
Related:
nuxt/scripts#297
#27442
#27364
Environment
Reproduction
https://stackblitz.com/github/exophunk/nuxt-doublemounted-issue
https://github.com/exophunk/nuxt-doublemounted-issue
The reproduction shows various circumstances where that issue happens. Details are described in the reproduction index page.
Steps:
Describe the bug
Whenever you are using pageTransition or layoutTransition in your app, the usage of any async function inside the
<setup>part of a page (or any child component) leads to faulty mounting the page twice!As
const { data } = await useFetch('...');is a very common in setup, the chances of this issue to happen is quite common. Whenever you have this on combination with transitions, mounting happens twice.Layout Transitions
layoutTransition: { mode: 'out-in', name: 'page', duration: 300 }Page Transitions
What is the problem?
Mounting a page twice (and mounting every child component twice) can lead to various unexpected bugs, especially for UI components that init themselves on mount or components that perform any idempotent actions or API calls. This can be very severe! In our case, a ecommerce checkout call was sent twice to the backend! And it was hard to spot or figure out why. Noone expects
onMounted()to happen twice.Quick fix workaround
To fix the issue, you can wrap
<NuxtPage />inside a<Suspense>.The Suspense Quick Fix seems to work fine. We have it in production now for about half a year. But I can't say if it has any drawbacks or creates issues elsewhere. It's also difficult to make sure our devs know of this workaround and do not create new pages without it.
Additional context
The issue was once further explained as a comment to #27364. The bug is open for +1 Year now.
I updated the reproduction to 3.17.5 and the bug persists.
I suggest closing the other, less clearly described issue and keep tracking this one.
If it's not an easy fix, then I would suggest that after 1 year, at least a warning in the documentation should be placed that page/layout transitions should be used with caution.
Related:
nuxt/scripts#297
#27442
#27364