From 73e2979cb8557148c450c0282a20acb2f3c6c642 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 10 Jul 2023 14:04:44 +0200 Subject: [PATCH] Ensure useParams return array for catch-all routes (#52494) ## What? Ensures `useParams` matches `params` passed to the page, also matches the docs. Fixes #50856 Fixes NEXT-1419 --- packages/next/src/client/components/navigation.ts | 10 ++++++++-- test/e2e/app-dir/use-params/app/[...path]/page.tsx | 13 +++++++++++++ test/e2e/app-dir/use-params/use-params.test.ts | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 test/e2e/app-dir/use-params/app/[...path]/page.tsx diff --git a/packages/next/src/client/components/navigation.ts b/packages/next/src/client/components/navigation.ts index 53c9f7d083ad6..349927f905a9c 100644 --- a/packages/next/src/client/components/navigation.ts +++ b/packages/next/src/client/components/navigation.ts @@ -127,7 +127,7 @@ export function useRouter(): import('../../shared/lib/app-router-context').AppRo } interface Params { - [key: string]: string + [key: string]: string | string[] } // this function performs a depth-first search of the tree to find the selected @@ -144,7 +144,13 @@ function getSelectedParams( const segmentValue = isDynamicParameter ? segment[1] : segment if (!segmentValue || segmentValue.startsWith('__PAGE__')) continue - if (isDynamicParameter) { + // Ensure catchAll and optional catchall are turned into an array + const isCatchAll = + isDynamicParameter && (segment[2] === 'c' || segment[2] === 'oc') + + if (isCatchAll) { + params[segment[0]] = segment[1].split('/') + } else if (isDynamicParameter) { params[segment[0]] = segment[1] } diff --git a/test/e2e/app-dir/use-params/app/[...path]/page.tsx b/test/e2e/app-dir/use-params/app/[...path]/page.tsx new file mode 100644 index 0000000000000..0bcb50b87ad23 --- /dev/null +++ b/test/e2e/app-dir/use-params/app/[...path]/page.tsx @@ -0,0 +1,13 @@ +'use client' +import { useParams } from 'next/navigation' +export default function Page() { + const params = useParams() + if (params === null) { + return null + } + return ( +
+
{JSON.stringify(params.path)}
+
+ ) +} diff --git a/test/e2e/app-dir/use-params/use-params.test.ts b/test/e2e/app-dir/use-params/use-params.test.ts index 36575d703e08b..df14f4f95f2c5 100644 --- a/test/e2e/app-dir/use-params/use-params.test.ts +++ b/test/e2e/app-dir/use-params/use-params.test.ts @@ -16,6 +16,11 @@ createNextDescribe( expect($('#param-id2').text()).toBe('b') }) + it('should work for catch all params', async () => { + const $ = await next.render$('/a/b/c/d/e/f/g') + expect($('#params').text()).toBe('["a","b","c","d","e","f","g"]') + }) + it('should work for single dynamic param client navigating', async () => { const browser = await next.browser('/') expect(