Skip to content

Core: Support array-based catch-all Next.js route segments in AppRouterProvider #31524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: next
Choose a base branch
from

Conversation

yatishgoel
Copy link
Contributor

@yatishgoel yatishgoel commented May 21, 2025

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 using useParams() 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's parameters.nextjs.navigation.segments.

The AppRouterProvider has been updated to:

  • Directly process parameters.nextjs.navigation.segments to construct the pathParams object provided to PathParamsContext.
  • Support segments defined as an array of [key, value] tuples (e.g., [['directories', ['a', 'b']]]).
  • Support segments defined as an object (e.g., { directories: ['a', 'b'] }), enhancing flexibility.
  • Ensure that if a value for a parameter is an array, it is preserved as an array, allowing useParams() to receive it correctly.

The getSelectedParams utility function was also made more robust to handle cases where a segment value within the FlightRouterState 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:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

  1. Generate a Next.js sandbox

    cd storybook
    yarn task --task sandbox --template nextjs/default-ts
  2. Start the sandbox in development mode

    cd sandbox/nextjs-default-ts
    yarn task --task dev --template nextjs/default-ts --start-from=install
    # or
    yarn storybook dev -p 6006
  3. Add a test component
    Create src/components/TestComponent.tsx inside the sandbox:

    'use client';
    import { useParams } from 'next/navigation';
    
    export function TestComponent() {
      const { items } = useParams<{ items?: string[] }>();
      return <div data-testid="items">{JSON.stringify(items || [])}</div>;
    }
  4. Add a corresponding story
    Create src/stories/TestComponent.stories.tsx:

    import type { Meta, StoryObj } from '@storybook/react';
    import { TestComponent } from '../components/TestComponent';
    
    const meta: Meta<typeof TestComponent> = {
      component: TestComponent,
      title: 'Sandbox/TestComponent',
      parameters: {
        nextjs: {
          appDirectory: true,
          navigation: {
            segments: [['items', ['one','two','three']]],
            pathname: '/test/one/two/three',
          },
        },
      },
    };
    export default meta;
    type Story = StoryObj<typeof TestComponent>;
    
    export const WithItems: Story = {};
  5. Verify in Storybook

    • Open the Sandbox → TestComponent story.
    • Confirm the <div data-testid="items"> renders ["one","two","three"].
    • Ensure no console errors occur and the parameter remains a string array.

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/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]].

  • Modified getSelectedParams in code/frameworks/nextjs/src/routing/app-router-provider.tsx to handle pre-existing array segment values
  • Updated pathParams generation to support both array tuples ([['key', ['value1', 'value2']]]) and object format segments
  • Added support for catch-all route parameters in useParams() hook responses
  • Synchronized changes between Next.js and Next.js-Vite framework implementations
  • Maintained backward compatibility while fixing array parameter handling for App Router

…arams (catch-all routes)\n\n- Allow array values in navigation.segments for useParams in stories\n- Improve type safety, avoid any\n- Support both array and object segment formats\n- Fixes issue with catch-all/optional catch-all dynamic routes in stories
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 file(s) reviewed, 2 comment(s)
Edit PR Review Bot Settings | Greptile

Copy link

nx-cloud bot commented May 21, 2025

View your CI Pipeline Execution ↗ for commit 680de70.

Command Status Duration Result
nx run-many -t build --parallel=3 ✅ Succeeded 1m 26s View ↗

☁️ Nx Cloud last updated this comment at 2025-05-22 17:44:33 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Next.js segments not accepting array
2 participants