DEV Community

loading...
Cover image for Contextual routing and modal routes in Next.js

Contextual routing and modal routes in Next.js

toomuchdesign profile image Andrea Carraro Updated on ・3 min read

Contextual routing is a widespread UI technic made popular by applications like Facebook, Instagram and Reddit usually in the shape of Modal Routes.

Modal routes pattern consists of opening a modal while temporary replacing the current URL (usually with the one pointing to the resource being displayed in-modal):

Basic contextual routing

Next.js router recently added support for contextual routing by simply providing Link component with the relevant href + as props.

import Link from 'next/link';

<Link
  href="/post-list?postId=42"
  as="/post/42"
>
  <a>Open modal route</a>
</Link>
Enter fullscreen mode Exit fullscreen mode

The above example would update browser address' path to /post/42 while rendering the page specified as href (/post-list with postId parameters equal to 42).

This leads to 2 possible outcomes:

  • user closes the modal and the URL is restored to the value where contextual routing was started (in our case /post-list)
  • user refreshes the page landing on the actual page described by the URL

HREF property

The minimal necessary information to render a Next.js page consists of:

  • page pathname (eg. /post/[id])
  • page params (eg. id=42)

The main idea behind contextual routing consists of creating a divergence between the URL displayed and the page actually rendered.

Since contextual navigation replaces the URL, it means that rendered pages cannot rely anymore on the URL to retrieve pathname and relative page params.

href prop plays therefore the crucial role of supplying the aforementioned information as a single string:

// page pathname + all required params as query string
const href = router.pathname + `?param1=1&param2=2`
Enter fullscreen mode Exit fullscreen mode

Real world scenario

Before starting contextual routing navigation you need to know 3 information beforehand:

  • as path (the path displayed during contextual routing)
  • href path
  • return href (the path to return to to end contextual routing)

href and return href are trivial to get when the starting page has a static path, let's say: /post-list.

Things gets trickier when starting page path is not statically defined, in other words when the path includes dynamic parameters like: /post-list/bob (where bob is an author name).

This means href has to be generated from initial page pathname plus route params and then persisted during the whole contextual routing navigation in order to keep the page alive.

On top of this a developer might want to extend available route params with extra ones to be made available during contextual navigation. Eg:

const as = 'post/42'
const returnHref = 'post-list/bob'
const href = 'post-list/[author]?author=bob&id=42'
Enter fullscreen mode Exit fullscreen mode

The example above provides id=42 as extra param to make the modal route aware of which post should be displayed.

This demo shows a basic implementation of what you just read.

The devil is in the details

There's is an extra pitfall worth mentioning: the application would loose reference to returnHref after a page reload followed by one or more back button presses.

This means the application won't be able to restore the initial URL while the modal route is open, breaking the user flow or forcing Next.js to reload the page.

One hook to rule them all

In order to overcome this issue and make contextual routing setup trivial, I wrapped the necessary boilerplate logic in a React hook published as next-use-contextual-routing.

You can read the source code and star it on github. It's fully tested and weights ~0.5 kb gzipped.

import Link from 'next/link';
import { useContextualRouting } from 'next-use-contextual-routing';

//...
const { makeContextualHref, returnHref } = useContextualRouting();

<Link
  as="/post/42"
  href={makeContextualHref({ id: 42 })}
  shallow
>
  <a>Open modal route</a>
</Link>

Enter fullscreen mode Exit fullscreen mode

The hook returns 2 values:

makeContextualHref: a function returning the href value necessary to start contextual navigation. It optionally accepts an object providing extra href parameters.

returnHref: the path to return to to close contextual navigation.

The demo mentioned above makes use of next-use-contextual-routing hook. Check it out to make sure it can suit your needs.

Discussion

pic
Editor guide
Collapse
vvo profile image
Vincent Voyer

Hey there, I featured this article in the latest Next.js News: twitter.com/vvoyer/status/13182876... (at the bottom of the newsletter content).

BTW, are you sure it's ~500 kb gzipped? Seems like a lot :)

Collapse
toomuchdesign profile image
Andrea Carraro Author

Hi Vincent, it's definitely a lot! I've just refactored the article's dev dependencies and the weight got down to 0.5kb :) Thank you