Skip to content

Commit

Permalink
Ensure metadata doesn't break scroll-to-top on navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Jan 10, 2025
1 parent 137ae4e commit 3fee0b4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 30 deletions.
15 changes: 10 additions & 5 deletions packages/next/src/server/app-render/create-component-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -399,25 +399,25 @@ async function createComponentTreeInternal({

const notFoundElement = NotFound ? (
<>
<NotFound />
{metadata}
{notFoundStyles}
<NotFound />
</>
) : undefined

const forbiddenElement = Forbidden ? (
<>
<Forbidden />
{metadata}
{forbiddenStyles}
<Forbidden />
</>
) : undefined

const unauthorizedElement = Unauthorized ? (
<>
<Unauthorized />
{metadata}
{unauthorizedStyles}
<Unauthorized />
</>
) : undefined

Expand Down Expand Up @@ -669,8 +669,13 @@ async function createComponentTreeInternal({
return [
actualSegment,
<React.Fragment key={cacheNodeKey}>
{metadata}
{pageElement}
{/*
* The order here matters since a parent might call findDOMNode().
* findDOMNode() will return the first child if multiple children are rendered.
* But React will hoist metadata into <head> which breaks scroll handling.
*/}
{metadata}
{layerAssets}
<OutletBoundary>
<MetadataOutlet ready={getViewportReady} />
Expand Down Expand Up @@ -805,12 +810,12 @@ async function createComponentTreeInternal({
notFound={
NotFound ? (
<>
{metadata}
{layerAssets}
<SegmentComponent params={params}>
{notFoundStyles}
<NotFound />
</SegmentComponent>
{metadata}
</>
) : undefined
}
Expand Down
55 changes: 30 additions & 25 deletions test/development/acceptance-app/hydration-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ describe('Error overlay for hydration errors in App router', () => {
const { session, browser } = sandbox
await session.openRedbox()

expect(await getRedboxTotalErrorCount(browser)).toBe(2)
await retry(async () => {
expect(await getRedboxTotalErrorCount(browser)).toBe(2)
})

// FIXME: Should also have "text nodes cannot be a child of tr"
expect(await session.getRedboxDescription()).toMatchInlineSnapshot(
Expand Down Expand Up @@ -439,7 +441,6 @@ describe('Error overlay for hydration errors in App router', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
<__next_metadata_boundary__>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
> <table>
Expand Down Expand Up @@ -567,7 +568,9 @@ describe('Error overlay for hydration errors in App router', () => {
const { session, browser } = sandbox
await session.openRedbox()

expect(await getRedboxTotalErrorCount(browser)).toBe(2)
await retry(async () => {
expect(await getRedboxTotalErrorCount(browser)).toBe(2)
})

const description = await session.getRedboxDescription()
expect(description).toContain(
Expand Down Expand Up @@ -665,7 +668,9 @@ describe('Error overlay for hydration errors in App router', () => {
const { session, browser } = sandbox
await session.openRedbox()

expect(await getRedboxTotalErrorCount(browser)).toBe(2)
await retry(async () => {
expect(await getRedboxTotalErrorCount(browser)).toBe(2)
})

const description = await session.getRedboxDescription()
expect(description).toEqual(outdent`
Expand Down Expand Up @@ -718,7 +723,9 @@ describe('Error overlay for hydration errors in App router', () => {
const { session, browser } = sandbox
await session.openRedbox()

expect(await getRedboxTotalErrorCount(browser)).toBe(2)
await retry(async () => {
expect(await getRedboxTotalErrorCount(browser)).toBe(2)
})

const description = await session.getRedboxDescription()
expect(description).toContain(
Expand Down Expand Up @@ -895,19 +902,18 @@ describe('Error overlay for hydration errors in App router', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
<__next_metadata_boundary__>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<div>
<div>
<div>
<div>
<div>
<Mismatch>
<p>
<span>
...
+ client
- server"
<Mismatch>
<p>
<span>
...
+ client
- server"
`)
} else {
expect(fullPseudoHtml).toMatchInlineSnapshot(`
Expand All @@ -916,19 +922,18 @@ describe('Error overlay for hydration errors in App router', () => {
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter url="/" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
<__next_metadata_boundary__>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
<Page params={Promise} searchParams={Promise}>
<div>
<div>
<div>
<div>
<div>
<Mismatch>
<p>
<span>
...
+ client
- server"
<Mismatch>
<p>
<span>
...
+ client
- server"
`)
}
})
Expand Down

0 comments on commit 3fee0b4

Please sign in to comment.