Core: Support array-based catch-all Next.js route segments in AppRouterProvider #31524
+56
−6
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #31523
What I did
This PR fixes an issue where the Next.js framework addon (for both Webpack and Vite) did not correctly handle array values for route parameters when using the App Router (
appDirectory: true
). Specifically, components usinguseParams()
for catch-all or optional catch-all routes (e.g.,[[...slug]]
or[...slug]
) would not receive the parameter as an array if specified as such in the story'sparameters.nextjs.navigation.segments
.The
AppRouterProvider
has been updated to:parameters.nextjs.navigation.segments
to construct thepathParams
object provided toPathParamsContext
.segments
defined as an array of[key, value]
tuples (e.g.,[['directories', ['a', 'b']]]
).segments
defined as an object (e.g.,{ directories: ['a', 'b'] }
), enhancing flexibility.value
for a parameter is an array, it is preserved as an array, allowinguseParams()
to receive it correctly.The
getSelectedParams
utility function was also made more robust to handle cases where a segment value within theFlightRouterState
might already be an array, preventing potential runtime errors.This change enables stories to accurately mock and test components that rely on array-based route parameters from Next.js's dynamic routing.
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Generate a Next.js sandbox
cd storybook yarn task --task sandbox --template nextjs/default-ts
Start the sandbox in development mode
Add a test component
Create
src/components/TestComponent.tsx
inside the sandbox:Add a corresponding story
Create
src/stories/TestComponent.stories.tsx
:Verify in Storybook
<div data-testid="items">
renders["one","two","three"]
.Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal
,ci:merged
orci:daily
GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.ts
Make sure this PR contains one of the labels below:
Available labels
bug
: Internal changes that fixes incorrect behavior.maintenance
: User-facing maintenance tasks.dependencies
: Upgrading (sometimes downgrading) dependencies.build
: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup
: Minor cleanup style change. Will not show up in release changelog.documentation
: Documentation only changes. Will not show up in release changelog.feature request
: Introducing a new feature.BREAKING CHANGE
: Changes that break compatibility in some way with current major version.other
: Changes that don't fit in the above categories.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/core
team here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>
Greptile Summary
Enhanced AppRouterProvider to properly handle array-based catch-all route segments in Next.js, ensuring correct parameter handling for dynamic routes like
[...slug]
and[[...slug]]
.getSelectedParams
incode/frameworks/nextjs/src/routing/app-router-provider.tsx
to handle pre-existing array segment valuespathParams
generation to support both array tuples ([['key', ['value1', 'value2']]]
) and object format segmentsuseParams()
hook responses