Intercepting Routes: Is there any way to determine if you are on an intercepted modal #82064
Replies: 2 comments 1 reply
-
Great question! With Next.js App Router’s intercepting routes (like modals), detecting whether you’re currently showing a modal versus the underlying “deep link” page can be tricky but doable. Possible approaches: Check search params or state Leverage useRouter history state Custom context or store Summary Let me know if you want example code snippets or help implementing this! |
Beta Was this translation helpful? Give feedback.
-
Short answer Pattern A — Slot context (recommended)File structure
'use client'
import { createContext, useContext } from 'react'
const ModalCtx = createContext(false)
export const useIsModal = () => useContext(ModalCtx)
export default function ModalLayout({ children }: { children: React.ReactNode }) {
return (
<ModalCtx.Provider value={true}>
{/* Render on top of the background route */}
{children}
</ModalCtx.Provider>
)
}
'use client'
import { useRouter } from 'next/navigation'
import { useIsModal } from '../layout'
export default function PhotoModal({ params }: { params: { id: string } }) {
const router = useRouter()
const isModal = useIsModal()
// You can now branch logic:
// render as a modal, add blur/backdrop, different close behavior, etc.
const close = () => {
// Prefer back if we have history, otherwise push to a safe route
if (history.length > 1) router.back()
else router.push(`/photo/${params.id}`)
}
return (
<div role="dialog" aria-modal="true">
<button onClick={close}>Close</button>
<img src={`/api/photos/${params.id}`} alt="" />
<p>isModal = {String(isModal)}</p>
</div>
)
}
export default async function PhotoPage({ params }: { params: { id: string } }) {
// Regular full-page rendering
return <img src={`/api/photos/${params.id}`} alt="" />
} Result: Pattern B — History-aware close behavior (optional)If you want different “close” logic depending on whether there’s a background route: 'use client'
import { useRouter } from 'next/navigation'
export function useSmartClose(fallbackHref: string) {
const router = useRouter()
return () => {
// `history.state?.idx` exists in Next.js app router navigations
const idx = (history.state && (history.state as any).idx) ?? 0
if (idx > 0) router.back()
else router.replace(fallbackHref)
}
} Use in the modal: const close = useSmartClose('/feed') Notes
If this helps, please Mark as answer so others can find it. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Scenario - our user has clicked on a photo in the feed and we have "fake" routed to the url such as photo/1234-23234-3434 and it opens in a modal via an intercepting route. This logic is working correctly.
Need a way to know which page we are actually on - behind the modal - because router.back() cannot be used for all scenarios, since we might need to know and pass this pathname around.
Need a way to determine from some way in the intercepting modal layout if we are in the intercepting modal url vs the actual deep link url
@modal / layout.tsx
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions