Parallel Routes in Next.js 14

Parallel Routes in Next.js 14

What are Parallel Routes?

parallel routes are an advanced routing mechanism that allows for the simultaneous rendering of multiple pages within the same layout. Let's explore this concept with a practical example.

Showcase:

Imagine that we want to display the login page when the user go to the route /sign-in but if he is in a different page like for example the e-commerce and he wants to navigate to /sign-in the route changes but we do not navigate to the page of login form instead we display the sign in modal where he can sign in directly from there .

Practical Example:

In this example we will see how we can implement the previous example but using the shopping cart of the user but first of all we need to know the difference between hard navigation and soft navigation.

  • Hard navigation: is when the user relaod / refresh the page .

  • Soft navigation: when the user navigate inside the app .

App Structure:

based on the folder structure we can see that we have page basket where we can see our shopping cart and we have a slot @modal which is used to define a parallel route for the basket route.

so when we are in another route different from /basket and we navigate to the route /basket the basket modal will be rendred from @modal/(.)basket/page.tsx folder but if we reload the page we go to the basket page from basket/page.tsx.

How we implemented it?

(.)basket/page.tsx

'use client';

import Basket from '@/components/Basket';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { useRouter } from 'next/navigation';

import { useCallback } from 'react';

function Modalpage() {
  const router = useRouter();

  const onDismiss = useCallback(() => {
    return router.back();
  }, [router]);

  return (
    <Dialog
      open
      onOpenChange={(isOpen) => {
        if (!isOpen) onDismiss();
      }}
    >
      <DialogContent className='h-4/5 w-full overflow-auto max-w-3xl'>
        <DialogHeader>
          <DialogTitle>Your Basket</DialogTitle>
          <Basket />
        </DialogHeader>
      </DialogContent>
    </Dialog>
  );
}

export default Modalpage;

you also can implement loading.tsx / error.tsx for our slot by creating these files under @modal/(.)basket .

you can read more about route intercepting and convention here

default.tsx is a fallback for our slot if we are not in the route /basket it will be rendred so we just returned null in this component because we do not want to render anything when we are not in the basket route:

function DefaultPage() {
  return null;
}

export default DefaultPage;

we defined the baseket/page.tsx that will be rendred when we hard navigate to this page :

import Basket from '@/components/Basket';
import { ShoppingCartIcon } from 'lucide-react';

function page() {
  return (
    <div className='w-full p-10 max-w-7xl mx-auto'>
      <div className='flex items-center space-x-2'>
        <ShoppingCartIcon className='w-10 h-10' />
        <h1 className='text-3xl font-'>Your Cart</h1>
      </div>
      <p className='mt-2 mb-5'>
        Review the items in your cart and checkout when ready!
      </p>
      <Basket />
    </div>
  );
}

export default page;

here is the root layout:

export default function RootLayout({
  children,
  modal,
}: Readonly<{
  children: React.ReactNode;
  modal: React.ReactNode;
}>) {
  return (
    <html lang='en'>
      <body className={inter.className}>
        <Header />
        <div className='flex flex-1 w-full'>
          {modal}
          {children}
        </div>
      </body>
    </html>
  );
}

Small Demo On The Behaviour:

we can see the basket page is rendred only when we reloaded the page (have navigation)

Conclusion:

Next.js 14's parallel routes offer a powerful way to build dynamic and complex user interfaces. This approach not only simplifies code management but also enhances user experience with independent route handling and sub-navigation.

Key Takeaways:

  • Parallel routes allow simultaneous rendering of different pages within the same layout.

  • Parallel routes are defined using slots.

  • Slots organize content in a modular fashion, making code more manageable.

  • The use of default.tsx for unmatched routes ensure a consistent user experience, even when certain content sections don't have a direct match in the URL.

  • Parallel Routes can be used to implement conditional routing.