From a79aa5068310c73354215dd125d0b1d2596fe505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Tue, 1 Nov 2022 14:22:08 +0100 Subject: [PATCH 1/4] Return empty string instead of throwing --- packages/next/client/components/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/client/components/navigation.ts b/packages/next/client/components/navigation.ts index 39b3d7092521fb7..67eaf9988a9194b 100644 --- a/packages/next/client/components/navigation.ts +++ b/packages/next/client/components/navigation.ts @@ -177,7 +177,7 @@ export function useSelectedLayoutSegment( ): string { const selectedLayoutSegments = useSelectedLayoutSegments(parallelRouteKey) if (selectedLayoutSegments.length === 0) { - throw new Error('No selected layout segment below the current level') + return '' } return selectedLayoutSegments[0] From 03fc39bb345fb184dc4d732691697302b31a9bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Tue, 1 Nov 2022 14:23:30 +0100 Subject: [PATCH 2/4] Add tests --- .../(group)/second/[...catchall]/page.js | 13 +++++-- .../first/layout.js | 11 ++++-- .../use-selected-layout-segment/layout.js | 11 ++++-- test/e2e/app-dir/index.test.ts | 34 ++++++++++++++++++- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/[dynamic]/(group)/second/[...catchall]/page.js b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/[dynamic]/(group)/second/[...catchall]/page.js index 470730ed05d66d3..5cda7e23cac8d81 100644 --- a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/[dynamic]/(group)/second/[...catchall]/page.js +++ b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/[dynamic]/(group)/second/[...catchall]/page.js @@ -1,11 +1,18 @@ 'use client' -import { useSelectedLayoutSegments } from 'next/navigation' +import { + useSelectedLayoutSegments, + useSelectedLayoutSegment, +} from 'next/navigation' export default function Page() { - const selectedLayoutSegment = useSelectedLayoutSegments() + const selectedLayoutSegments = useSelectedLayoutSegments() + const selectedLayoutSegment = useSelectedLayoutSegment() return ( -

{JSON.stringify(selectedLayoutSegment)}

+ <> +

{JSON.stringify(selectedLayoutSegments)}

+

{JSON.stringify(selectedLayoutSegment)}

+ ) } diff --git a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/layout.js b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/layout.js index 6db1338e8278364..e79045c5ed1e7be 100644 --- a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/layout.js +++ b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/first/layout.js @@ -1,13 +1,18 @@ 'use client' -import { useSelectedLayoutSegments } from 'next/navigation' +import { + useSelectedLayoutSegments, + useSelectedLayoutSegment, +} from 'next/navigation' export default function Layout({ children }) { - const selectedLayoutSegment = useSelectedLayoutSegments() + const selectedLayoutSegments = useSelectedLayoutSegments() + const selectedLayoutSegment = useSelectedLayoutSegment() return ( <> -

{JSON.stringify(selectedLayoutSegment)}

+

{JSON.stringify(selectedLayoutSegments)}

+

{JSON.stringify(selectedLayoutSegment)}

{children} ) diff --git a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/layout.js b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/layout.js index 5d7974142e40f6d..3eeae83e65da1be 100644 --- a/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/layout.js +++ b/test/e2e/app-dir/app/app/hooks/use-selected-layout-segment/layout.js @@ -1,13 +1,18 @@ 'use client' -import { useSelectedLayoutSegments } from 'next/navigation' +import { + useSelectedLayoutSegments, + useSelectedLayoutSegment, +} from 'next/navigation' export default function Layout({ children }) { - const selectedLayoutSegment = useSelectedLayoutSegments() + const selectedLayoutSegments = useSelectedLayoutSegments() + const selectedLayoutSegment = useSelectedLayoutSegment() return ( <> -

{JSON.stringify(selectedLayoutSegment)}

+

{JSON.stringify(selectedLayoutSegments)}

+

{JSON.stringify(selectedLayoutSegment)}

{children} ) diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 338dd701459237f..54185028b1a931b 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -1268,7 +1268,7 @@ describe('app dir', () => { } }) - describe('useSelectedLayoutSegment', () => { + describe('useSelectedLayoutSegments', () => { it.each` path | outerLayout | innerLayout ${'/hooks/use-selected-layout-segment/first'} | ${['first']} | ${[]} @@ -1298,6 +1298,38 @@ describe('app dir', () => { expect(JSON.parse($('#page-layout-segments').text())).toEqual([]) }) }) + + describe('useSelectedLayoutSegment', () => { + it.each` + path | outerLayout | innerLayout + ${'/hooks/use-selected-layout-segment/first'} | ${'first'} | ${''} + ${'/hooks/use-selected-layout-segment/first/slug1'} | ${'first'} | ${'slug1'} + ${'/hooks/use-selected-layout-segment/first/slug2/second/a/b'} | ${'first'} | ${'slug2'} + `( + 'should have the correct layout segments at $path', + async ({ path, outerLayout, innerLayout }) => { + const html = await renderViaHTTP(next.url, path) + const $ = cheerio.load(html) + + expect(JSON.parse($('#outer-layout-segment').text())).toEqual( + outerLayout + ) + expect(JSON.parse($('#inner-layout-segment').text())).toEqual( + innerLayout + ) + } + ) + + it('should return an empty string in pages', async () => { + const html = await renderViaHTTP( + next.url, + '/hooks/use-selected-layout-segment/first/slug2/second/a/b' + ) + const $ = cheerio.load(html) + + expect(JSON.parse($('#page-layout-segment').text())).toEqual('') + }) + }) }) if (isDev) { From 7e3fcb27aa6bc0bab14ea3cae4135a3d8445979c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 2 Nov 2022 09:59:30 +0100 Subject: [PATCH 3/4] Return null instead --- packages/next/client/components/navigation.ts | 4 ++-- test/e2e/app-dir/index.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/next/client/components/navigation.ts b/packages/next/client/components/navigation.ts index 67eaf9988a9194b..0d5f4dde633feb4 100644 --- a/packages/next/client/components/navigation.ts +++ b/packages/next/client/components/navigation.ts @@ -174,10 +174,10 @@ export function useSelectedLayoutSegments( */ export function useSelectedLayoutSegment( parallelRouteKey: string = 'children' -): string { +): string | null { const selectedLayoutSegments = useSelectedLayoutSegments(parallelRouteKey) if (selectedLayoutSegments.length === 0) { - return '' + return null } return selectedLayoutSegments[0] diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 54185028b1a931b..91c594212db9ae1 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -1302,7 +1302,7 @@ describe('app dir', () => { describe('useSelectedLayoutSegment', () => { it.each` path | outerLayout | innerLayout - ${'/hooks/use-selected-layout-segment/first'} | ${'first'} | ${''} + ${'/hooks/use-selected-layout-segment/first'} | ${'first'} | ${null} ${'/hooks/use-selected-layout-segment/first/slug1'} | ${'first'} | ${'slug1'} ${'/hooks/use-selected-layout-segment/first/slug2/second/a/b'} | ${'first'} | ${'slug2'} `( @@ -1327,7 +1327,7 @@ describe('app dir', () => { ) const $ = cheerio.load(html) - expect(JSON.parse($('#page-layout-segment').text())).toEqual('') + expect(JSON.parse($('#page-layout-segment').text())).toEqual(null) }) }) }) From 40479453aae188a61c9f3baa5b13cc7dccf3353f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 2 Nov 2022 10:18:01 +0100 Subject: [PATCH 4/4] test names fixed --- test/e2e/app-dir/index.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 91c594212db9ae1..d43f4d46f251c1b 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -1306,7 +1306,7 @@ describe('app dir', () => { ${'/hooks/use-selected-layout-segment/first/slug1'} | ${'first'} | ${'slug1'} ${'/hooks/use-selected-layout-segment/first/slug2/second/a/b'} | ${'first'} | ${'slug2'} `( - 'should have the correct layout segments at $path', + 'should have the correct layout segment at $path', async ({ path, outerLayout, innerLayout }) => { const html = await renderViaHTTP(next.url, path) const $ = cheerio.load(html) @@ -1320,7 +1320,7 @@ describe('app dir', () => { } ) - it('should return an empty string in pages', async () => { + it('should return null in pages', async () => { const html = await renderViaHTTP( next.url, '/hooks/use-selected-layout-segment/first/slug2/second/a/b'