Skip to content

Commit

Permalink
Ensure useParams return array for catch-all routes (#52494)
Browse files Browse the repository at this point in the history
## What?

Ensures `useParams` matches `params` passed to the page, also matches the docs.

Fixes #50856
Fixes NEXT-1419
  • Loading branch information
timneutkens committed Jul 10, 2023
1 parent cf08f60 commit 73e2979
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
10 changes: 8 additions & 2 deletions packages/next/src/client/components/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
}

Expand Down
13 changes: 13 additions & 0 deletions test/e2e/app-dir/use-params/app/[...path]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client'
import { useParams } from 'next/navigation'
export default function Page() {
const params = useParams()
if (params === null) {
return null
}
return (
<div>
<div id="params">{JSON.stringify(params.path)}</div>
</div>
)
}
5 changes: 5 additions & 0 deletions test/e2e/app-dir/use-params/use-params.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit 73e2979

Please sign in to comment.