diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index d0005eb6e7148..d192970eec658 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -319,13 +319,11 @@ async function generateFlight( flightRouterState, isFirst: true, // For flight, render metadata inside leaf page - rscPayloadHead: ( - <> - - {/* Adding requestId as react key to make metadata remount for each render */} - - - ), + // NOTE: in 14.2, fragment doesn't work well with React, using array instead + rscPayloadHead: [ + , + , + ], injectedCSS: new Set(), injectedJS: new Set(), injectedFontPreloadTags: new Set(), @@ -531,12 +529,12 @@ async function ReactServerError({ const head = ( <> - {/* Adding requestId as react key to make metadata remount for each render */} {process.env.NODE_ENV === 'development' && ( )} + ) diff --git a/test/e2e/app-dir/metadata-navigation/app/(cart)/product/layout.tsx b/test/e2e/app-dir/metadata-navigation/app/(cart)/product/layout.tsx new file mode 100644 index 0000000000000..1fae4138eb8a2 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/(cart)/product/layout.tsx @@ -0,0 +1,13 @@ +import { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Product Layout', +} + +export default function Layout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return <>{children} +} diff --git a/test/e2e/app-dir/metadata-navigation/app/(cart)/product/page.tsx b/test/e2e/app-dir/metadata-navigation/app/(cart)/product/page.tsx new file mode 100644 index 0000000000000..6fda1b09db3e0 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/(cart)/product/page.tsx @@ -0,0 +1,3 @@ +export default function Page() { + return
Product page content
+} diff --git a/test/e2e/app-dir/metadata-navigation/app/@header/layout.tsx b/test/e2e/app-dir/metadata-navigation/app/@header/layout.tsx new file mode 100644 index 0000000000000..15286d515a67f --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/@header/layout.tsx @@ -0,0 +1,7 @@ +type LayoutProps = { + children: React.ReactNode +} + +export default function Layout({ children }: LayoutProps) { + return
{children}
+} diff --git a/test/e2e/app-dir/metadata-navigation/app/@header/page.tsx b/test/e2e/app-dir/metadata-navigation/app/@header/page.tsx new file mode 100644 index 0000000000000..029e01e2ad355 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/@header/page.tsx @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Page() { + return ( +
+
Home header
+ + Product + +
+ ) +} diff --git a/test/e2e/app-dir/metadata-navigation/app/@header/product/layout.tsx b/test/e2e/app-dir/metadata-navigation/app/@header/product/layout.tsx new file mode 100644 index 0000000000000..cd0e8d61beece --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/@header/product/layout.tsx @@ -0,0 +1,7 @@ +type LayoutProps = { + children: React.ReactNode +} + +export default function Layout({ children }: LayoutProps) { + return <>{children} +} diff --git a/test/e2e/app-dir/metadata-navigation/app/@header/product/page.tsx b/test/e2e/app-dir/metadata-navigation/app/@header/product/page.tsx new file mode 100644 index 0000000000000..11b27614e0630 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/@header/product/page.tsx @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Page() { + return ( +
+

Product header

+ + Go to Home page + +
+ ) +} diff --git a/test/e2e/app-dir/metadata-navigation/app/layout.tsx b/test/e2e/app-dir/metadata-navigation/app/layout.tsx new file mode 100644 index 0000000000000..e05cd2dd3ed58 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/layout.tsx @@ -0,0 +1,23 @@ +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Home Layout', + description: 'Generated by create next app', +} + +export default function RootLayout({ + header, + children, +}: Readonly<{ + header: React.ReactNode + children: React.ReactNode +}>) { + return ( + + + {header} + {children} + + + ) +} diff --git a/test/e2e/app-dir/metadata-navigation/app/page.tsx b/test/e2e/app-dir/metadata-navigation/app/page.tsx new file mode 100644 index 0000000000000..92b0c4de98772 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/app/page.tsx @@ -0,0 +1,7 @@ +export default function Home() { + return ( +
+

Home page content

+
+ ) +} diff --git a/test/e2e/app-dir/metadata-navigation/metadata-navigation.test.ts b/test/e2e/app-dir/metadata-navigation/metadata-navigation.test.ts new file mode 100644 index 0000000000000..10accfbc6d7c4 --- /dev/null +++ b/test/e2e/app-dir/metadata-navigation/metadata-navigation.test.ts @@ -0,0 +1,30 @@ +import { createNextDescribe } from 'e2e-utils' + +createNextDescribe( + 'app-dir - metadata-navigation', + { + files: __dirname, + }, + ({ next }) => { + it('should show the index title', async () => { + const browser = await next.browser('/') + expect(await browser.elementByCss('title').text()).toBe('Home Layout') + }) + + it('should show target page metadata after navigation', async () => { + const browser = await next.browser('/') + await browser.elementByCss('#product-link').click() + await browser.waitForElementByCss('#product-title') + expect(await browser.elementByCss('title').text()).toBe('Product Layout') + }) + + it('should show target page metadata after navigation with back', async () => { + const browser = await next.browser('/') + await browser.elementByCss('#product-link').click() + await browser.waitForElementByCss('#product-title') + await browser.elementByCss('#home-link').click() + await browser.waitForElementByCss('#home-title') + expect(await browser.elementByCss('title').text()).toBe('Home Layout') + }) + } +)