Skip to content
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

Intercepting routes don’t work with route groups #53170

Closed
1 task done
kachkaev opened this issue Jul 25, 2023 · 15 comments
Closed
1 task done

Intercepting routes don’t work with route groups #53170

kachkaev opened this issue Jul 25, 2023 · 15 comments
Labels
bug Issue was opened via the bug report template. locked Parallel & Intercepting Routes Related to Parallel and/or Intercepting routes.

Comments

@kachkaev
Copy link
Contributor

kachkaev commented Jul 25, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.5.0: Thu Jun  8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.16.0
      npm: 9.5.1
      Yarn: 1.22.19
      pnpm: 8.6.10
    Relevant Packages:
      next: 13.4.13-canary.1
      eslint-config-next: 13.4.13-canary.1
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.6
    Next.js Config:
      output: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App Router

Link to the code that reproduces this issue or a replay of the bug

https://github.com/kachkaev/next-js-intercepting-routes-in-groups-mwe

Here is the ‘product spec’:

The app is a photo browser, similar to nextgram.
There are three navigation pages:

  1. Home page (recent photos)
  2. top photos
  3. best photo

When users navigate to a photo on the first two pages, it should open in a modal.
When users navigate to a photo on the third page, it should open in a new page, not in a modal.
Each photo page has previous / next links. Neighbouring photos open in the same way: in a modal or in a new page*.


* When I add previous / next links in the nextgram app, neighbouring photos always open in a modal. This creates modals on the standalone photo page, which is what I am trying to avoid:

nextrgram-previous-next.mp4

To Reproduce

  1. Clone the repo:

    git clone https://github.com/kachkaev/next-js-intercepting-routes-in-groups-mwe.git
    cd next-js-intercepting-routes-in-groups-mwe
    pnpm install
    pnpm dev
  2. Inspect the folder structure:

    app/
    ├── (no-modal)
    │   ├── best-photo
    │   │   └── page.tsx
    │   ├── layout.tsx
    │   └── photo
    │       └── page.tsx
    ├── (with-modal)
    │   ├── @modal
    │   │   ├── (...)photo
    │   │   │   └── page.tsx
    │   │   ├── page.tsx
    │   │   └── top-photos
    │   │       └── page.tsx
    │   ├── layout.tsx
    │   ├── page.tsx
    │   └── top-photos
    │       └── page.tsx
    └── layout.tsx

    Here is the technical solution I have come up with based on the docs:

    • There is a root layout for global navigation, CSS reset, custom fonts, etc.
    • There are two route groups called (no-modal) and (with-modal).
    • Home page and ‘top photos’ page are in the (with-modal) group.
    • The layout file in this group contains a slot called @modal which renders a photo page using an intercepting route.
    • The ‘best photo’ page is in the (no-modal) group, together with the photo page itself.
    • In addition to the intercepting route for a photo, app/(with-modal)/@modal also contains dummy routes for the home page and the ‘top photos’ page to avoid 404s. I know it is possible to add default or catch-all routes to this folder too, but doing so would blur the distinction between the two route groups and thus make the reproduction a bit less vivid.

    The reproduction example does not use dynamic routes for simplicity. Photo ids are encoded in a GET param. Going for photo/[id] produces the same results (see below).

  3. Open http://localhost:3000 and navigate between the home page and the ‘top photos’ page. Click on individual photo links within these pages and observe them opened in the modal, as expected. We are in the same route group called (with-modal), all works fine so far.

    happy-path.mp4
  4. Broken scenario 1: While on a photo page, press refresh in the browser. Observe that the photo page is opened in a new page, not in a modal. This is expected. Now try navigating to a previous or a next photo and observe an error:

    Unhandled Runtime Error
    Error: notFound() is not allowed to use in root layout
    
    broken-scenario-1.mp4
  5. Broken scenario 2: Navigate to the ‘best photo’ page and observe that it uses (no-modal) layout, as expected. Navigate to a photo page and observe the same error as above.

    broken-scenario-2.mp4
  6. Broken scenario 3: Open the photo page and observe that it uses (no-modal) layout, as expected. Make a small tweak in /app/(no-modal)/photo/page.tsx to trigger hot reloading. Observe notFound() error again:

    broken-scenario-3

Describe the Bug

Seems like Next.js is unable to deal with intercepting routes and route groups at the same time. Presence of app/(with-modal)/@modal/(...)photo/page.tsx breaks navigation to /photo from pages where this route is not intercepting.

The same happens for dynamic routes (i.e. when /photo?id=123 is replaced with /photo/123). See the PR #1 in the reproduction repo.

  →    

Expected Behavior

I would expect that the app would work according to product spec described earlier. The folder structure I have come up with seems to match Next.js docs for the listed requirements. Avoiding modals at least on the photo page is crucial and I am not sure how to do this without using route groups and intercepting routes.

Perhaps, this is just a matter of docs and I am just missing something. I have been trying various workarounds for quite a few hours last weekend but have not solved the problem no matter what I have tried. Hope that the reproduction example is helpful.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

I have not tried deploying this app yet, but if I try pnpm build && pnpm start, navigation remains broken in the same scenarios as during pnpm dev. There are two key differences:

  1. Error message says:
    Application error: a server-side exception has occurred (see the server logs for more information).
    Digest: NEXT_NOT_FOUND
    
  2. Unlike in pnpm dev, browser URL does not update when a broken link is followed.
pnpm-build-start.mp4

PS: Despite this situation and some level of frustration caused by it, I find the new router pretty awesome. So let me use this bug report as an opportunity to thank the Next.js community for working on it! I know that some developers struggle with the new model because of the things they’ve got used to, but I do see a lot of value in the change! Epic stuff! 👏

@arobert93

This comment has been minimized.

@unoscar

This comment was marked as off-topic.

@thongbn
Copy link

thongbn commented Aug 19, 2023

mine same problem , work fine in dev mode but 404 in production build
Here is my project folder
image

Still render and working in dev mode
image

@bilalesi

This comment was marked as off-topic.

@jmarbutt

This comment was marked as off-topic.

@jma1020

This comment has been minimized.

@wawle

This comment has been minimized.

@ghost
Copy link

ghost commented Jan 11, 2024

il mio stesso problema, funziona bene in modalità sviluppatore ma 404 nella build di produzione Ecco la cartella del mio progetto Immagine

Esegui ancora il rendering e funziona in modalità sviluppatore Immagine

I have the same problem

@decanTyme
Copy link

decanTyme commented Mar 18, 2024

Here's my setup after following the docs:

image

I basically wanted to group all settings stuff so it doesn't clutter when I'm not working on it. It should intercept and overlay on whatever's in /[user], but I only get a 404. The odd thing is that the (.)settings does get imported by the fact that:

image

// app/(settings)/@settings/(.)settings/page.tsx
export default function SettingsIntercept() {
  console.log("SettingsIntercept!")

  return (
    <Modal>
      <SettingsSidebar />
    </Modal>
  )
}

Only works when I yank both @settings and settings out of (settings) and put them into app directly.

@balazsorban44 balazsorban44 added the Parallel & Intercepting Routes Related to Parallel and/or Intercepting routes. label Apr 19, 2024
@VolodymyrDatsiuk
Copy link

mine same problem , work fine in dev mode but 404 in production build Here is my project folder image

Still render and working in dev mode image

JUst curious: are yours (.)cart/page.tsx and cart/page.tsx the same?

@ztanner
Copy link
Member

ztanner commented Apr 24, 2024

Hi @kachkaev (and others)! Apologies for the delay in responding. Recently I've been working through the various parallel routes & interception routes issues. I took a look at the provided reproduction and I was able to get all scenarios working as expected, so I think we were able to address the problems you were running into!

Scenario 1

CleanShot.2024-04-23.at.17.33.11.mp4

Scenario 2

CleanShot.2024-04-23.at.17.34.17.mp4

Scenario 3

CleanShot.2024-04-23.at.17.37.17.mp4

The only thing I noticed that was missing was a app/(with-modal)/default.tsx file to handle the case where the children slot in app/(with-modal)/layout.tsx isn't matched with a page route (as is the case currently when it triggers route interception).

I'm going to close this issue, but happy to answer any additional questions, or look at other bug reproductions. Thank you!

@ztanner ztanner closed this as completed Apr 24, 2024
@chochoZusebmt
Copy link

chochoZusebmt commented Apr 24, 2024

Hi @kachkaev (and others)! Apologies for the delay in responding. Recently I've been working through the various parallel routes & interception routes issues. I took a look at the provided reproduction and I was able to get all scenarios working as expected, so I think we were able to address the problems you were running into!

Scenario 1

CleanShot.2024-04-23.at.17.33.11.mp4

Scenario 2

CleanShot.2024-04-23.at.17.34.17.mp4

Scenario 3

CleanShot.2024-04-23.at.17.37.17.mp4
The only thing I noticed that was missing was a app/(with-modal)/default.tsx file to handle the case where the children slot in app/(with-modal)/layout.tsx isn't matched with a page route (as is the case currently when it triggers route interception).

I'm going to close this issue, but happy to answer any additional questions, or look at other bug reproductions. Thank you!

Hi @ztanner

Thanks for your solution.

Please post application file structure and maybe source code for corresponding files. I'm facing this issue and nextjs documentation doesn't give enough information.

EDIT:

FOUND A WORKING SOLUTION!

Above solution doesn't fix this specific issue. If your route is a direct child of your route group, the only solution is to use [...catchAll]/page.tsx in the same folder as your interceptor to catch that bad boy. In my case I ended up with /app/(root)/foo/@bar/(...)photos/ and /app/(root)/foo/@bar/[...catchAll]/page.tsx. You'll have to create your own logic to decide what gets rendered. The object provided by the catchAll parameter can tell you which files you were trying to call.

2nd Edit:

It would be awesome if someone could add a snippet on how to render an expected route using dynamic imports. But this solution will have to do for now.

@olehakon
Copy link

The only thing I noticed that was missing was a app/(with-modal)/default.tsx file to handle the case where the children slot in app/(with-modal)/layout.tsx isn't matched with a page route (as is the case currently when it triggers route interception).

Can you elaborate on why this is the case? Aren't the children defined when navigating to an intercepted route? Am I missing something here?

@ztanner
Copy link
Member

ztanner commented Apr 26, 2024

The only thing I noticed that was missing was a app/(with-modal)/default.tsx file to handle the case where the children slot in app/(with-modal)/layout.tsx isn't matched with a page route (as is the case currently when it triggers route interception).

Can you elaborate on why this is the case? Aren't the children defined when navigating to an intercepted route? Am I missing something here?

In the provided repro, the app transitions to a new layout (from app/(no-modal)/layout.tsx to app/(with-modal)/layout.tsx. The route that's transitioned to matches the interception route (which fills the @modal slot), but nothing matches to the children slot. When a slot is encountered for the first time and it can't find a match, it uses default.tsx. The default default.tsx behavior is to throw a notFound() error.

Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. locked Parallel & Intercepting Routes Related to Parallel and/or Intercepting routes.
Projects
None yet
Development

No branches or pull requests