#Problem with Next.js Interception route

88 messages · Page 1 of 1 (latest)

icy cypress
#

I am using next.js v15 app router.
I have a button in page.tsx
When clicking that button I want to show this route [id]/page.tsx as modal on the page.
When I refresh the page, I want to show the modal, not standalone page.
How can I implement this approach?

sand tokenBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

acoustic knot
#

It sounds like you don't want an interception route at all. When you refresh the page, you want it to show the modal on top of the same [id]/page.tsx?

violet viper
#

In that case, you don't need to use interception route, btw if you wanna still use that, you can implement the modal(open) in the default.tsx.

acoustic knot
#

If that is the case, the modal route needs to know the [id] as well. I think the best way to do so is with parallel routes, putting the modal at /[id]/modal or something like that.

app/
├─ [id]/
│  ├─ layout.tsx
│  ├─ page.tsx
│  ├─ @modal/
│  │  ├─ default.tsx
│  │  ├─ modal/
│  │  │  ├─ page.tsx

in the default parallel route, render nothing. In the modal/ one, render the modal.

icy cypress
#

@acoustic knot
Why I have to use modal/page.tsx? Can I use page.tsx directly in @modal?

acoustic knot
#

no; @modal creates the parallel route, meaning [id]/layout.tsx will get an additional param called modal containing whatever routes match in @modal. That's why you have @modal/default.tsx and @modal/modal/page.tsx. The route is what maters for the URL. if you wanted the modal at [id]/login or [id]/edit you would use @modal/login/page.tsx or @modal/edit/page.tsx instead.

#

I forgot to mention the [id]/layout.tsx file. You would change it to render both children and modal.

icy cypress
#

What will be the url to access that modal in that case?

acoustic knot
#

I also may be wrong here; I'm not sure the behavior of parallel routes on the [id]/page.tsx

violet viper
#

Maybe the reason why you want to use interception route is route.

#

@acoustic knot, in your case, the modal should be removed in the @modal.

#
app/
├─ [id]/
│  ├─ layout.tsx
│  ├─ page.tsx
│  ├─ @modal/
│  │    ├─ page.tsx
acoustic knot
#

in that case, the modal would always show.

icy cypress
#

This is the my project structure

acoustic knot
#

Unless you added conditional rendering to it or something. Prince, can you explain what you want the end result to be?

icy cypress
#

So I want to show modal over work-requests/page.tsx

acoustic knot
#

And when they refresh?

icy cypress
#

Still shows modal when refresh

acoustic knot
#

still shows the modal over the same [codename]/[id]?

#

or, just shows the modal over the work requests page?

icy cypress
#

[codename]/[id] is modal route. I want to show that modal on work-requests/page.tsx when refresh

acoustic knot
#

ok. So, user is on work-requests, goes to work-requests/[codename]/[id], and you want it to show a modal over the top of the work-requests page. Then, when they refresh or directly visit work-requests/[codename]/[id], it should still show the modal over the work-requests page?

icy cypress
#

Corret

violet viper
#

@icy cypress, so in that case, what do you want to show when the user click history back?

acoustic knot
violet viper
#

work-requests page or work-requests/[codename]/[id] page with hidden modal?

acoustic knot
#

When you visit work-requests, the layout will recieve whatever work-requests/@modal/default.tsx renders, and will recieve work-requests/page.tsx for children.

When you visit work-requests/[codename]/[id], layout will recieve whatever work-requests/[codename]/[id]/page.tsx renders for modal, and work-requests/page.tsx for children.

violet viper
#

So if you want to show the modal still even the user refresh the current page.
You have to implement the opened modal in the default.tsx.

#

And for this you have to use interception route.

acoustic knot
#

I don't think that's what they're asking Demi. It sounds like there is no modal when they are on work-requests and only when at work-requests/[codename]/[id] should a modal appear, specifically ABOVE whatever work-requests is showing, and should remain even when refreshing.

violet viper
#

@acoustic knot, you forgot to mention about the interception route.

icy cypress
acoustic knot
#

Demi, I dont think an interception route is appropriate, because it should render the SAME thing regardless of how it's reached.

violet viper
#

Let's point that the route.

#

We can solve the modal opened when the user refresh using the default.tsx.

#

Default, the default.tsx returns nulll.

#

But in this case, @icy cypress should render the opened modal in the default.tsx

#

Except this, the others are same as interception route.

#

Of course, @icy cypress have to use parallel route too.

icy cypress
#

I did like this but getting 404 error

acoustic knot
#

oh oh,

icy cypress
#

/work-requests/[codename]/[id]

violet viper
#

Just a sec, I will show you something.

acoustic knot
#

default.tsx should go directly in @modal

icy cypress
violet viper
acoustic knot
#

ah, I think that I was wrong on how children behaves. Could you rename work-requests/page.tsx to work-requests/default.tsx?

icy cypress
# violet viper

In this approach, it shows [codename]/[id]/page.tsx when refresh, and shows @modal/(.)/[id]/page.tsx when navigating. I don't want that

violet viper
#

@modal/(.)/[id]/page.tsx ?

#

@modal/(.)[id]/page.tsx

icy cypress
acoustic knot
#

ok. If you duplicate page.tsx to default.tsx; Also, I think we may be overcomplicating this. let me write something out.

icy cypress
#

I don't think I have to update /work-requests/page.tsx

#

There's no problem with that file

acoustic knot
#

yeah, just copy that file

#

to work-requests/default.tsx

#

and if it works, you can refactor it's contents to share it between both. I'm not 100% sure tho

icy cypress
#

But it doesn't work

icy cypress
acoustic knot
#

You want work-requests/page.tsx to render for sub-routes as well, i.e. under this modal. I think the simplest way to do it is by moving it's contents to a layout file, as this is the purpose of the layout file. You could do so by doing something like this:

app/
├─ work-requests/
│  ├─ layout.tsx
│  ├─ page.tsx
│  ├─ [codename]/[id]/
│  │  ├─ page.tsx

with work-requests/layout.tsx containing your current work-requests/page.tsx contents and also rendering children, work-requests/page.tsx rendering nothing, but allowing the route to be accessed (i.e., the url example.com/work-requests renders work-requests/layout.tsx and work-requests/page.tsx), and the modal in [codename]/[id]/page.tsx.

icy cypress
acoustic knot
#

If work-requests has other routes which should NOT render the work requests page, for example work-requests/options or seomething of the sort, you could use a route group so that the layout will not render for those, and will only render for the other routes.

#
├─ work-requests/
│  ├─ (modal)
│  │  ├─ layout.tsx
│  │  ├─ page.tsx
│  │  ├─ [codename]/[id]/
│  │  │  ├─ page.tsx
│  ├─ (non-modal)
│  │  ├─ ... other subroutes
#

and (non-modal) shouldn't contain any matching routes for work-requests/; only for subroutes like work-requests/options etc.

icy cypress
#

Showing page content in layout.tsx is not the best practice. I hope there's another way

acoustic knot
#

You could make work-requests/page.tsx a optional catch-all route, and then programatically show the modal. i.e. work-requests/[[...path]]/page.tsx

#

I jsut went and tested it myself, this is what worked for me.

icy cypress
#

can you please show what you updated?

acoustic knot
#
  1. localhost:3000/test shows the contents of /test/page.tsx and /test/@modal/default.tsx
  2. localhost:3000/test/modal shows the contents of /test/modal/page.tsx and /test/@modal/modal/page.tsx
#

I modified it to use a common component for both /test/page.tsx and /test/modal/page.tsx because that's what you want to do. I'll upload a gist and share it

#

the files are commented at the top where they go

violet viper
#

So @acoustic knot, is it working in your case?

acoustic knot
#

yes.

sand tokenBOT
acoustic knot
#

Here's one more way to do it. This would be if you want a common backdrop page for the modal, and potentially you have multiple modals. I've attached screenshots showing the behavior

violet viper
#

Using this way, we can implement the purpose also, but in this case, we can use the advantages of interception route such as route back, and show modal and full screen modal when the user refresh.

acoustic knot
# violet viper Using this way, we can implement the purpose also, but in this case, we can use ...

I think your implementation is fine, but not what Prince asked for. Prince explicitly wants the behavior to be the SAME, regardless of whether the user gets to the modal from work-requests or directly navigates to it (i.e, on refresh). In the case of what Prince wants, intercept routes are not applicable, because the behavior needs to be the same, regardless of how the user reaches the route.

violet viper
#

Yes, agree.

#

But using this way, we can acheive @icy cypress's purpose also.

#

After refreshing.