Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NextJS dynamic routing with modal reload causing overlay background to disappear

I have a very simple NextJS app where opening a page will update the URL but won't trigger a navigation and will instead display the content inside a modal. The URL still reflects the actual page location and any refresh brings the user there.

When the modal open, I want to still keep the original content off the page faded in the background and the modal should come to the front.

Right now when my modal opens, the original background content disappears rather than faded in the background.

I've replicated the issue in code-sandbox : https://codesandbox.io/s/replicating-backdrop-disappearing-rqt21?file=/pages/index.js

In the code-sandbox example, when you click the login button, you will see the modal works but the original background disappears. How can I get the background content to just be faded.

Please help.

like image 905
breaktop Avatar asked Feb 10 '21 22:02

breaktop


People also ask

Does router push reload the page?

push by default doesn't trigger a page reload #21787.

How do I force a refresh on Nextjs?

import Router from 'next/router'; Router. reload(); This will force the reload but without the hook, allowing you to do it wherever you need it outside of component function.

What is shallow routing Nextjs?

Shallow routing allows you to change the URL without running data fetching methods again, that includes getServerSideProps , getStaticProps , and getInitialProps . You'll receive the updated pathname and the query via the router object (added by useRouter or withRouter ), without losing state.


1 Answers

As mentioned in the documentation, what you're attempting to do is not possible/practical. You can't simultaneously keep a page loaded while loading another page. If you want to keep the same page loaded, then you'll have to utilize dynamic routes with shallow routing, which I feel is overkill for static authentication pages.

Instead, you should either create a Layout component that wraps over the entire app (using _app.js) or selectively wrap each route with a reusable layout component.

On a side note, I'd recommend avoiding importing the same 3rd party global CSS more than once. If you're importing it more than once, it's a sign that you most likely should be using Next's custom app page for global stylesheets (not required, but should eliminate redundant stylesheet imports).

Demo:

Edit NextJS Layout


components/Layout/index.jsx

/* eslint-disable jsx-a11y/anchor-is-valid */
import Link from "next/link";

export default function Layout({ children }) {
  return (
    <>
      <Link href="/">
        <a className="link">Home</a>
      </Link>
      <Link href="/login">
        <a className="link">Login</a>
      </Link>
      <Link href="/signup">
        <a className="link">Signup</a>
      </Link>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Itaque eos id
        agere, ut a se dolores, morbos, debilitates repellant. Duo Reges:
        constructio interrete. Qualis ista philosophia est, quae non interitum
        afferat pravitatis, sed sit contenta mediocritate vitiorum? Vide ne ista
        sint Manliana vestra aut maiora etiam, si imperes quod facere non
        possim. <i>Quid censes in Latino fore?</i> Ita relinquet duas, de quibus
        etiam atque etiam consideret. <i>Quippe: habes enim a rhetoribus;</i>{" "}
        <b>Sum praesertim illa perdiscere ludus esset.</b>{" "}
      </p>
      {children}
    </>
  );
}

/* eslint-enable jsx-a11y/anchor-is-valid */

pages/_app.js

import "react-responsive-modal/styles.css";
import Layout from "../components/Layout";
import "../styles.css";

export default function App({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

pages/index.js

export default function IndexPage() {
  return <h1>Index Page</h1>;
}

pages/login.js

import Router from "next/router";
import { Modal } from "react-responsive-modal";

export default function Login() {
  return (
    <Modal center blockScroll open onClose={() => Router.push("/")}>
      <p>Login</p>
    </Modal>
  );
}

pages/signup.js

import Router from "next/router";
import { Modal } from "react-responsive-modal";

export default function SignupPage() {
  return (
    <Modal center blockScroll open onClose={() => Router.push("/")}>
      <p>Signup</p>
    </Modal>
  );
}
like image 191
Matt Carlotta Avatar answered Sep 21 '22 12:09

Matt Carlotta