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

Parallel routes do not clear slot with [...catchAll] #48719

Closed
1 task done
Yukioru opened this issue Apr 22, 2023 · 14 comments · Fixed by #58215
Closed
1 task done

Parallel routes do not clear slot with [...catchAll] #48719

Yukioru opened this issue Apr 22, 2023 · 14 comments · Fixed by #58215
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation.

Comments

@Yukioru
Copy link

Yukioru commented Apr 22, 2023

Verify canary release

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

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP Fri Jan 27 02:56:13 UTC 2023
Binaries:
  Node: 19.7.0
  npm: 9.5.0
  Yarn: N/A
  pnpm: 8.8.0
Relevant Packages:
  next: 13.5.4-canary.1
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: N/A
Next.js Config:
  output: N/A

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

App directory (appDir: true), Routing (next/router, next/navigation, next/link)

Link to the code that reproduces this issue

/~https://github.com/Yukioru/next-parallel-routes-bug
https://codesandbox.io/p/github/Yukioru/next-parallel-routes-bug/main
https://next-parallel-routes-bug.vercel.app

To Reproduce

You have to use soft navigation

  1. Click "To /overview" page
  2. Slot displays correctly with contents of the "Overview Extension"
  3. Click "To /demo" page
  4. The slot has not cleared

image

Describe the Bug

Once the slot is shown, it is not cleared if the URL does not match.
A similar bug has already been described in Issue: #48124, but the solution with [...catchAll] route did not help. The route is not called.

If you do a hard navigation, you will see that the /demo slot segment corresponds to the default.js route, but it does not show up.

Expected Behavior

Using soft navigation (next/link) the slot should be cleared by the [...catchAll] route (or the default.js route if possible).

Which browser are you using? (if relevant)

Chrome 112.0.5615.138

How are you deploying your application? (if relevant)

Vercel, CodeSandbox

NEXT-1394

@Yukioru Yukioru added the bug Issue was opened via the bug report template. label Apr 22, 2023
@github-actions github-actions bot added area: app App directory (appDir: true) Navigation Related to Next.js linking (e.g., <Link>) and navigation. labels Apr 22, 2023
@y0zong
Copy link

y0zong commented Apr 30, 2023

like I mentioned here#48090, it seems dynamic route or catch-all route still not compatible with parallel route, I think it may have some work to do.

@Yukioru
Copy link
Author

Yukioru commented May 12, 2023

Did a little research on the code - the essence of the problem is that all /[...catchAll] match only with [...catchAll] pages. When the situation arises that [...catchAll] the route is only in the parallel segment, but not on the page - the router will wait for the transition to the [...catchAll] page (if in my Issue go to a non-existent page, the segment will be called).

It seems that appPaths should contain any of the [...catchAll] being in a segment (but not necessarily having a page) considering nesting.

const originalPageName = pageName
pageName = normalizeAppPath(pageName).replace(/%5F/g, '_')
if (!appPaths[pageName]) {
appPaths[pageName] = []
}
appPaths[pageName].push(originalPageName)

Perhaps there is a similar code in other packages for generating pages (I could not find it correctly)..


For example
Now page matchers look like this:

{
  "/": ["/page", "/@extension/page"],
  "/[...catchAll]": ["/@extension/[...catchAll]/page"],
  "/overview": ["/overview/page", "/@extension/overview/page"],
  "/demo": ["/demo/page"]
}

But they should look like this:

{
  "/": ["/page", "/@extension/page"],
  "/[...catchAll]": ["/@extension/[...catchAll]/page"],
  "/overview": ["/overview/page", "/@extension/overview/page"],
  "/demo": ["/demo/page", "/@extension/[...catchAll]/page"]
}

@adidoes
Copy link

adidoes commented Jun 23, 2023

I just ran into this issue on 13.4.7. Has anyone found a workaround?

@timneutkens timneutkens added the linear: next Confirmed issue that is tracked by the Next.js team. label Jul 4, 2023
@oswaldoacauan
Copy link

Any updates on this? Right now feels impossible to use Parallel routes with Dynamic routes.

@tangye1234
Copy link
Contributor

Any progress?

@miro-zone
Copy link

tired many things nothing work just route.back() ... and yeah still we need fix.

@Yukioru
Copy link
Author

Yukioru commented Sep 27, 2023

Updated the issue to the latest canary version 13.5.4-canary.1
🗿waiting..

@tangye1234
Copy link
Contributor

Updated the issue to the latest canary version 13.5.4-canary.1
🗿waiting..

Could you see this issue? The whole app is unmounted in the case described there without any error.

@gragland
Copy link

gragland commented Sep 30, 2023

Here's a workaround:

app
├─ @photoModal
│  ├─ (.)photo
|  |  └─ [id]
│  │  |  └─ page.tsx <----- a modal with links to home, /profile, and /login
│  └─ [...catchAll]
│  │  └─ page.tsx <----- returning null here is supposed to cause modal to hide when
│  │  │                  navigating away, as this should match all other routes, doesn't work though.
│  │  │                  So we create dummy pages to match the specific routes below.
│  └─ profile             
│  │  └─ page.tsx <----- page that returns null, causing modal to hide when navigating to /profile
│  └─ login
│  │  └─ page.tsx <----- page that returns null, causing modal to hide when navigating to /login
|  └─ page.tsx <----- page that returns null, causing modal to hide when navigating to /
|  └─ default.tsx
├─ photo
|  └─ [id] 
|  |  └─ page.tsx 
├─ profile
│  └─ page.tsx
|  login
|  └─ page.tsx
└─ page.tsx

Dummy page looks like this:

export default function Page() {
  return null
}

@stefanofa
Copy link

Since I ran into the same problem, I also created a simple codesandbox.

The desired result is that the subheader that is displayed following a soft navigation to /c is "I'm the catchall subheader!"

@stefanofa
Copy link

I have created a draft PR with failed tests and further context, if anyone would like to add feedback please feel free to do so.

@feedthejim
Copy link
Contributor

thanks @stefanofa for adding a repro. I was looking into this and you're right that it should work. I'll try to fix this in the next one-two weeks. It's not super straightforward to fix unfortunately.

@stefanofa
Copy link

Thanks @feedthejim for taking care of it. Since this is part of the topic, I have a question to ask, namely why do the slots during soft navigation behave as described in the docs?

image

Thinking about it I can't think of any concrete use cases, although I'm most likely missing something.

@kodiakhq kodiakhq bot closed this as completed in #58215 Nov 9, 2023
kodiakhq bot pushed a commit that referenced this issue Nov 9, 2023
This PR fixes a bug where parallel routes would not apply appropriately on navigation when used within slots.

The following scenarios:
```
/foo
   /bar
   /@slot
     /[...catchAll]
```

or 

```
/foo
  /[...catchAll]
  /@slot
     /bar
```

will now function correctly when accessing /foo/bar, and Next.js will render both /bar and the catchall slots.

The issue was that the tree constructed by `next-app-loader` for a given path, /foo/bar in the example, would not include the paths for the catch-all files at build time. The routing was done 1-1 when compiling files, where a path would only match one file, with parallel routes, a path could hit a defined path but also a catch all route at the same time in a different slot.

The fix consists of adding another normalisation layer that will look for all catch-all in `appPaths` and iterate over the other paths and add the relevant information when needed.

The tricky part was making sure that we only included the relevant paths to the loader: we don't want to overwrite a slot with a catch all if there's already a more specific subpath in that slot, i.e. if there's /foo/@slot/bar/page.js, no need to inject /foo/@slot/bar/[...catchAll]. 

One thing that is not supported right now is optional catch all routes, will add later.

fixes #48719
fixes #49662
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 Nov 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants