Skip to content

Commit 050d13e

Browse files
authored
Make catchall parameters consistent with existing router (#38456)
Ensures catchall parameters are passed as an array to `params` instead of as a string. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
1 parent a4668f2 commit 050d13e

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

packages/next/server/app-render.tsx

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,11 @@ export async function renderToHTML(
409409
const getDynamicParamFromSegment = (
410410
// [id] or [slug]
411411
segment: string
412-
): { param: string; value: string } | null => {
412+
): {
413+
param: string
414+
value: string | string[] | null
415+
treeValue: string
416+
} | null => {
413417
// TODO: use correct matching for dynamic routes to get segment param
414418
const segmentParam = getSegmentParam(segment)
415419
if (!segmentParam) {
@@ -422,24 +426,20 @@ export async function renderToHTML(
422426
if (segmentParam.type === 'optional-catchall') {
423427
return {
424428
param: key,
425-
value: '',
429+
value: null,
430+
treeValue: '',
426431
}
427432
}
428433
return null
429434
}
430435

436+
// TODO: this should only read from `pathParams`. There's an inconsistency where `query` holds params currently which has to be fixed.
437+
const value = pathParams[key] ?? query[key]
438+
431439
return {
432440
param: key,
433-
value:
434-
// TODO: this should only read from `pathParams`. There's an inconsistency where `query` holds params currently which has to be fixed.
435-
(Array.isArray(pathParams[key])
436-
? // @ts-expect-error TODO: handle case where value is an array
437-
pathParams[key].join('/')
438-
: pathParams[key]) ??
439-
(Array.isArray(query[key])
440-
? // @ts-expect-error TODO: handle case where value is an array
441-
query[key].join('/')
442-
: query[key]),
441+
value: value,
442+
treeValue: Array.isArray(value) ? value.join('/') : value,
443443
}
444444
}
445445

@@ -450,7 +450,7 @@ export async function renderToHTML(
450450
const dynamicParam = getDynamicParamFromSegment(segment)
451451

452452
const segmentTree: FlightRouterState = [
453-
dynamicParam ? [dynamicParam.param, dynamicParam.value] : segment,
453+
dynamicParam ? [dynamicParam.param, dynamicParam.treeValue] : segment,
454454
{},
455455
]
456456

@@ -506,16 +506,16 @@ export async function renderToHTML(
506506
: undefined
507507

508508
const segmentParam = getDynamicParamFromSegment(segment)
509-
510-
const currentParams = segmentParam
511-
? {
512-
...parentParams,
513-
[segmentParam.param]: segmentParam.value,
514-
}
515-
: parentParams
516-
509+
const currentParams =
510+
// Handle null case where dynamic param is optional
511+
segmentParam && segmentParam.value !== null
512+
? {
513+
...parentParams,
514+
[segmentParam.param]: segmentParam.value,
515+
}
516+
: parentParams
517517
const actualSegment = segmentParam
518-
? [segmentParam.param, segmentParam.value]
518+
? [segmentParam.param, segmentParam.treeValue]
519519
: segment
520520

521521
// This happens outside of rendering in order to eagerly kick off data fetching for layouts / the page further down
@@ -539,7 +539,7 @@ export async function renderToHTML(
539539
const childProp: ChildProp = {
540540
current: <ChildComponent />,
541541
segment: childSegmentParam
542-
? [childSegmentParam.param, childSegmentParam.value]
542+
? [childSegmentParam.param, childSegmentParam.treeValue]
543543
: parallelRoutes[currentValue][0],
544544
}
545545

@@ -669,25 +669,26 @@ export async function renderToHTML(
669669
// TODO: throw on invalid flightRouterState
670670
const walkTreeWithFlightRouterState = (
671671
treeToFilter: LoaderTree,
672-
parentParams: { [key: string]: any },
672+
parentParams: { [key: string]: string | string[] },
673673
flightRouterState?: FlightRouterState,
674674
parentRendered?: boolean
675675
): FlightDataPath => {
676676
const [segment, parallelRoutes] = treeToFilter
677677
const parallelRoutesKeys = Object.keys(parallelRoutes)
678678

679679
const segmentParam = getDynamicParamFromSegment(segment)
680+
const currentParams =
681+
// Handle null case where dynamic param is optional
682+
segmentParam && segmentParam.value !== null
683+
? {
684+
...parentParams,
685+
[segmentParam.param]: segmentParam.value,
686+
}
687+
: parentParams
680688
const actualSegment: Segment = segmentParam
681-
? [segmentParam.param, segmentParam.value]
689+
? [segmentParam.param, segmentParam.treeValue]
682690
: segment
683691

684-
const currentParams = segmentParam
685-
? {
686-
...parentParams,
687-
[segmentParam.param]: segmentParam.value,
688-
}
689-
: parentParams
690-
691692
const renderComponentsOnThisLevel =
692693
!flightRouterState ||
693694
!matchSegment(actualSegment, flightRouterState[0]) ||

0 commit comments

Comments
 (0)