Coding 5 (Parallel Routes) More advanced topics # **Parallel Routes** - Parallel routes are similar to using multiple React components in a layout.jsx file like this Structure ```text src/app complex-dashboard users.jsx reviews.jsx notifications.jsx page.jsx layout.jsx components card.jsx ``` In `src/app/complex-dashboard/layout.jsx` ```jsx import Notifications from "./notifications"; import Reviews from "./reviews"; import Users from "./users"; export default function ComplexDashboardLayout({ children }) { return ( <>
{children}
{/* Contents from page.jsx */}
{/* Contents from users.jsx */} {/* Contents from reviews.jsx */}
{/* Contents from notifications.jsx */}
); } ``` In `src/app/complex-dashboard/page.jsx` ```jsx export default function ComplexDashboard() { return

Complex Dashboard

; } ``` In `src/app/complex-dashboard/users.jsx` ```jsx import Card from "../components/card"; export default function Users() { return Users; } ``` Similarly in `reviews.jsx` and `notifications.jsx` In `src/app/components/card.jsx` ```jsx export default function Card({ children }) { const cardStyle = { padding: "100px", margin: "10px", boxShadow: "0 4px 8px 0 rgba(0,0,0,0.2)", border: "1px solid #ddd", display: "flex", justifyContent: "center", alignItems: "center", }; return
{children}
; } ```   **Doing same with parallel routes** - We have to use slots as they help structure our content in modular fashion - We will use the '@folder_name' convention - Each slot is passed as a prop to its corresponding 'layout.jsx' file Transfer the files users.jsx, reviews.jsx and notifications.jsx like this ```bash cd $projectRoot/src/app/complex-dashboard mv users.jsx @users/page.js mv reviews.jsx @reviews/page.js mv notifications.jsx @notifications/page.js ``` Make sure that instead of 'page.jsx' 'page.js' should be used as that is expected from slots. Components may not rendered if `page.jsx` is used. Sometimes slot is not added in next so restart the dev server in such case. Structure ```text src/app complex-dashboard @users page.js @reviews page.js @notifications page.js page.jsx layout.jsx components card.jsx ``` In `src/app/complex-dashboard/layout.jsx` ```jsx export default function ComplexDashboardLayout({ children, notifications, users, reviews, }) { console.log("users: ", users); return ( <>
{children}
{/* Contents from page.jsx */}
{users} {/* Contents from users.jsx */} {reviews} {/* Contents from reviews.jsx */}
{notifications} {/* Contents from notifications.jsx */}
); } ```   Benefits of using parallel routes - Ability to split a single layout into various slots, making the code more manageable though it is also possible with components Coming to main benefits which is not possible with components - Independent route handling Unlike components, these slots can have their own loading and error states as they r handled like other routes without changing the url stack This gives more control where different sections load at varying speeds or encounter unique errors. ![806ab46a3d11ebdd3d3d54109f75f173.png](../../../../_resources/806ab46a3d11ebdd3d3d54109f75f173.png) - Sub navigation in routes - Each slot can function as their own mini application with their own navigation and state management. If we try to navigate to another route using components then it would be different as component is part of the page and when using `Link` component to change route then whole page has to be loaded so other component will not appear unless they r specifically rerendered in new page ![95bfea8e37d940bf5923d25fe037d8c4.png](../../../../_resources/95bfea8e37d940bf5923d25fe037d8c4.png)     # Unmatched Routes - Adding a sub navigation in notifications slot Structure ```text src/app complex-dashboard @users page.js @reviews page.js @notifications archived page.jsx page.js page.jsx layout.jsx components card.jsx ``` In `src/app/complex-dashboard/@notifications/archived/page.jsx` ```jsx import Card from "@/app/components/card"; import Link from "next/link"; export default function Notifications() { return (
Archived Notifications
Default
); } ``` In `src/app/complex-dashboard/@notifications/page.js` ```jsx import Card from "@/app/components/card"; import Link from "next/link"; export default function Notifications() { return (
Notifications
Archived
); } ``` When user click on the link named 'Archived' then archived will be added in route so our route will change from `localhost:3000/complex-dashboard` to `localhost:3000/complex-dashboard/archived`. - In layout.jsx there r 4 slots ie props.children, users, reviews and notifications. At `localhost:3000/complex-dashboard/archived` props.children, users, reviews are unmatched routes as archived folder is inside notifications slot. - When navigating witin the UI and not adding `archived` directly with browser, nextjs retains the previously active state of a slot regardless of changes in the URL - During page reload or directly typing archived in url we will get the error 404 if default.jsx is not found in corresponding unmatched slots. Even if one default.jsx is missing in any unmatched slot 404 error will there instead of other matched components getting loaded. - Adding `default.jsx` in unmatched slot is neccessary as it serves as fallback to render contents when nextjs cannot retrieve a slot's active state from the current URL. - We can define the UI for unmatched routes in any way in default.jsx and also mirror the content found in corresponding page.jsx. Adding `default.jsx` in unmatched slots ```bash # copying contents to default.jsx from page.jsx cd $projectRoot/src/app/complex-dashboard cp page.js default.js cp @users/page.js @users/default.js cp @reviews/page.js @reviews/default.js ``` Structure ```text src/app complex-dashboard @users default.js page.js @reviews default.js page.js @notifications archived page.jsx page.js default.js page.jsx layout.jsx components card.jsx ```     # Conditional Routes - With parallel routes it is possible to have conditional routes like login page or register page depending upon state and benefits with loading and error state and sub navigation unlike using component directly. - Ternary operators can be used for conditional rendering Structure ```text src/app complex-dashboard @login.jsx default.js page.js @users default.js page.js @reviews default.js page.js @notifications archived page.jsx page.js default.js page.jsx layout.jsx components card.jsx ``` In `src/app/complex-dashboard/@login/page.js` and `src/app/complex-dashboard/@login/default.js` ```jsx import Card from "@/app/components/card"; export default function Login() { return Please login to continue; } ``` In `src/app/complex-dashboard/layout.jsx` ```jsx export default function ComplexDashboardLayout({ children, notifications, users, reviews, login, }) { // if true that 'please login to continue' section wont appear const isLoogedIn = false; return isLoogedIn ? ( <>
{children}
{/* Contents from page.jsx */}
{users} {/* Contents from users.jsx */} {reviews} {/* Contents from reviews.jsx */}
{notifications} {/* Contents from notifications.jsx */}
) : ( login ); } ``` Make sure that default.js file also exist which can be same as page.js for login slot