javascriptreactjsnext.jsnext.js13nextjs-dynamic-routing

How can you use Link navigation to navigate away from an intercepted route in Next.js 13?


DISCLAIMER: I originally filed this as a bug in the Next.js github repo, but it was not recognised as an issue and was promptly closed. The explanation/solution that was given did not work for me so this means I must be doing something wrong, ergo the question here.

The question/problem

I have this demo app (codesandbox source here) which makes use of two Next.js routing features: Parallel routes and route interceptors

In short, clicking on a photo changes the URL from / to /photos/[id] but unless you reload the page, the photo is shown in a modal on top of the previous route view, instead of completely changing the page to the photo details page, which is neat.

Clicking the modal overlay invokes the router.back() function, which takes us one step back in the history stack, the URL changes to / and the photo modal is no longer shown, as expected.

Now, I have ended up with a scenario where I need to be able to navigate away from the modal with an actual Link component instead of calling router.back(). This means the user should be able to click the link that points away from /photos/[id], the URL should change to where the link is pointing and the modal should disappear.

However as you can see in the demo this is not the case.

What happens instead is the user clicks the link that points away from /photos/[id], the URL changes to where the link is pointing but the modal stays where it is. You can observe this behaviour even if you click on the link that takes you to a completely unrelated page.

Initially I thought maybe the problem is somehow the Link component and attempted to replace it with something like

    <button
      className="action"
      onClick={() => {
        router.push(`/`);
      }}
    >
      Close
    </button>

Yet it still does not work. It seems like invoking router.push('/') works somehow differently from router.back() even though both result in the URL changing to /.

If this somehow intended behaviour it is really strange, because apart from being counter intuitive, the docs themselves read

If a modal was initiated through client navigation, e.g. by using , you can dismiss the modal by calling router.back() or by using a Link component. (source)

The bolded part is what really throws me off.

As suggested in the comment left on the issue, I tried the solution with the [...catchAll] route; I tried moving it around from app/ to app/@modal/ to app/@modal/(..)photos/ and see in which dir it will work as described and it did not work.

So, is this a bug, or I am terribly misusing and misunderstanding something in the way the router and the router interception works?

If it's the latter how can you make the Link navigation work from intercepted routes?

Thanks.


Solution

  • Turns out this was in fact an issue with Next.js and the ticket I submitted which had been closed initially got reopened (see the link to the GitHub issue report in the question disclaimer). Should be fixed in one of the next patch versions updates of Next.js