Next.js router to open and close modal

I’ve tried using Parallel Routes to create a modal but am a bit confused on how to ignore the page from getting a new modal from the slot.

In this case, the color page has a lot of color harmonies that have links to other color pages and should not open a modal.

1. Homepage

Color palettes based on hue.

2. Color Red Modal

Every time a user clicks on another link color, it changes the content inside the modal.

3. Color Red Page

On this page the modal or slot should be ignored.

4. Color Rose

It should open a color page without opening a modal.

5. Color Rose Modal

How does the slot not know that the page it is in is the current page?

6. Color Rose Image (API Response)

Attempt to open another page to clear the previous state.

7. Color Rose Page

The previous state is lost because <Link /> has the replace=true prop, otherwise it would still be there but without the modal.


Closing the Modal

Yes, we can close the modal by calling router.back(), what if we can close them using router.push("/") then redirect to homepage and close the modal.

Why using replace=true?

In the image above you can see the arrow_back button to return to the previous state, and the hidden button as an overlay to close the modal. If I don’t replace the page, the hidden button don’t work like the arrow_back button. both call the same function.

const router = useRouter();

const handleClose = () => {
  router.back();
};

Using router.push() as alternative to close modal

This solution it will help edge cases that we don’t know, such as using <Link /> with replace=true and don’t have previous state. See above image with number (3-4 and 5).

const router = useRouter();

const handleClose = () => {
 if(typeof window !== "undefined"){
   if(window.history.length <= 1){
     router.push('/');
   } else {
     router.back();
   }
 }
};

Add prop modal=true as optional to open modal

This solution should prevent opening modal within page for the same page. See above image with number (4 and 5).

<Link href="/color/ff0080" modal={isModal ? true : false} {...} />

By adding modal=false prop the modal should be ignored and <Link /> should behave as usual.


Sorry to the team reading this messy feedback, but I can’t wait for this <Link modal={isModal ? true : false} />. Thank You!

Additional feedback about Metadata. Currently I’m writing a custom function that changes the homepage title to the current page title inside a modal.

const title = `Color: ${currentColor}`;

useEffect(() => {
  // save homepage title
  const pageTitle = document.title;

  // set currentColor page title
  document.title = title;

  return () => {
    // set homepage title
    document.title = pageTitle;
  };
},[title]);

I wish I could use function generateMetadata() inside ~/app/@portal/(.)color/page.tsx or within modal.

I finally found a workaround, by pushing the link through the router when there is no history, then every time the modal changes to its new content, the page stays there.

"use client";

import type { ComponentPropsWithoutRef } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";

interface Props extends Omit<ComponentPropsWithoutRef<"a">, "href" | "modal"> {
  href: string;
  modal: boolean;
}

export default function Porter({ href, modal, children, ...props }: Props) {
  const router = useRouter();
  return (
    <Link
      href={href}
      prefetch={false}
      replace={true}
      scroll={false}
      onClick={(e) => {
        if (!modal) {
          e.preventDefault();
          router.push(href);
        }
      }}
      {...props}
    >
      {children}
    </Link>
  );
}

By using this method we know if the current page has no history then any link with replace=true will be replaced with replace=false and the router saves the current page when the user tries to close the modal.

1 Like

Yes, the link has been fixed but ignoring the modal in the current page is still an issue.

From the docs: if navigating to any other page (such as /foo , /foo/bar , etc), you can use a catch-all slot

export default function CatchAll() {
  return null
}

I guess this catch-all route is ignoring all the params not searchParams.

1 Like

Thank you for coming back with the solution that worked for you!

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.