diff --git a/packages/nuxt/src/pages/runtime/page.ts b/packages/nuxt/src/pages/runtime/page.ts index f46a34a593e..d1e22f797d2 100644 --- a/packages/nuxt/src/pages/runtime/page.ts +++ b/packages/nuxt/src/pages/runtime/page.ts @@ -1,4 +1,4 @@ -import { DefineComponent, defineComponent, h, inject, provide, Suspense, Transition } from 'vue' +import { computed, DefineComponent, defineComponent, h, inject, provide, reactive, Suspense, Transition } from 'vue' import { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouterView } from 'vue-router' import { generateRouteKey, RouterViewSlotProps, wrapInKeepAlive } from './utils' @@ -33,14 +33,16 @@ export default defineComponent({ default: (routeProps: RouterViewSlotProps) => { if (!routeProps.Component) { return } + const key = generateRouteKey(props.pageKey, routeProps) + return _wrapIf(Transition, routeProps.route.meta.pageTransition ?? defaultPageTransition, wrapInKeepAlive(routeProps.route.meta.keepalive, isNested && nuxtApp.isHydrating // Include route children in parent suspense - ? h(Component, { key: generateRouteKey(props.pageKey, routeProps), routeProps } as {}) + ? h(Component, { key, routeProps, pageKey: key } as {}) : h(Suspense, { onPending: () => nuxtApp.callHook('page:start', routeProps.Component), onResolve: () => nuxtApp.callHook('page:finish', routeProps.Component) - }, { default: () => h(Component, { key: generateRouteKey(props.pageKey, routeProps), routeProps } as {}) }) + }, { default: () => h(Component, { key, routeProps, pageKey: key } as {}) }) )).default() } }) @@ -56,9 +58,20 @@ export default defineComponent({ const defaultPageTransition = { name: 'page', mode: 'out-in' } const Component = defineComponent({ - props: ['routeProps'], + // eslint-disable-next-line vue/require-prop-types + props: ['routeProps', 'pageKey'], setup (props) { - provide('_route', props.routeProps.route) + // Prevent reactivity when the page will be rerendered in a different suspense fork + const previousKey = props.pageKey + const previousRoute = props.routeProps.route + + // Provide a reactive route within the page + const route = {} + for (const key in props.routeProps.route) { + route[key] = computed(() => previousKey === props.pageKey ? props.routeProps.route[key] : previousRoute[key]) + } + + provide('_route', reactive(route)) return () => h(props.routeProps.Component) } })