Coding 3 **Link Component Navigation** - To enable client-side navigation Next.js provides us with the Link component. - The `` component is a React component that extends the HTML `` element and is primary way for navigation - To use it, we need to import it from 'next/link'. Structure ```text src/app blog page.jsx products page.jsx page.jsx ``` In `src/app/page.jsx` ```jsx import Link from "next/link"; const Home = () => { return ( <>

Hello

Blog Products ); }; export default Home; ``` In `src/app/blog/page.jsx` `/` path is used to go to root page ```jsx import Link from "next/link"; export default function Blog() { return ( <>

Blog

Home ); } ``` **For Dynamic Routes** Structure ```text src/app blog page.jsx products [productId] page.jsx page.jsx page.jsx ``` In `src/app/products/page.jsx` ```jsx import Link from "next/link"; export default function ProductList() { const productId = 100; return ( <>

Product List

Product 1

Product 2

{" "}

Product 3

{" "} {" "}

Product {productId}

{" "} ); } ``` - Link for Dynmaic routes is generated just like we access the value of variable. With `replace` keyword we can clear the url stack history means after navigating to `localhost:3000/products/3` and when we click back button we will navigate to `localhost:3000` not `localhost:3000/products`.   **Active Links** - First we need to create links for login, register, forgot-password in layout.jsx page for `(auth)`. So instead of creating these 3 links for each page ie login, register and forgot-password we used layout.jsx to serve this as template/same for all route groups. Structure ```text src/app (auth) login password forgot-password layout.jsx page.jsx ``` In `src/app/(auth)/layout.jsx` ```jsx import Link from "next/link"; const navLinks = [ { name: "Register", href: "/register" }, { name: "Login", href: "/login" }, { name: "Forgot Password", href: "/forgot-password" }, ]; export default function OuterAuthLayout({ children }) { return (
{navLinks.map((link) => { return {link.name}; })} {children}
); } ``` - So in order to style it we need to know the path of current url so we need to use the `usePathname` from 'next/navigation' hook. As we r using hook we need client side rendering for this and have to type `use client` at top in jsx file. Structure ```text src/app (auth) login password forgot-password layout.jsx style.css page.jsx ``` In `src/app/(auth)/layout.jsx`. Use the particular class for active link ```jsx "use client"; import Link from "next/link"; import { usePathname } from "next/navigation"; import "./style.css"; const navLinks = [ { name: "Register", href: "/register" }, { name: "Login", href: "/login" }, { name: "Forgot Password", href: "/forgot-password" }, ]; export default function OuterAuthLayout({ children }) { const pathname = usePathname(); return (
{navLinks.map((link) => { const isActive = pathname.startsWith(link.href); return ( {link.name} ); })} {children}
); } ``` In `src/app/(auth)/style.css` ```css a { margin: 0 1rem; color: blue; } a.active-link { color: black; } ```   **Navigating Programitically** - Instead of using jsx, javascript can be used too so for that we can use the hook ie `useRouter` from 'next/navigation'. Structure ```text src/app order-product page.jsx page.jsx ``` In `src/app/order-product/page.jsx` ```jsx "use client"; import { useRouter } from "next/navigation"; export default function OrderProduct() { const router = useRouter(); const handleClick = () => { console.log("order placed"); router.push("/"); }; return ( <>

Order Product

); } ``` router.push('/') will push the root route to url stack and when we click on back after going through homepage it will brink back to the page `localhost:3000/order-product`. In `Link` coponent there was a attribute named replace which clears the url stack so to do same programitically use `router.replace('/')`. Not only that but we can go to previous or next url stack too by `router.back()` and `router.forward()`   **Templates** - Templates are similar to layouts in the way they wrap each child layout or page But with templates when a user navigates between routes that share a template, a new instance of component is mounted, DOM elements are recreated, state is not preserved. - So to only to be used once we dont have to conserve states and need a template to recreate pages so their states dont conflict with each other Without template ```text src/app (auth) login password forgot-password layout.jsx style.css page.jsx ``` In `src/app/(auth)/layout.jsx` ```jsx "use client"; import Link from "next/link"; import { usePathname } from "next/navigation"; import "./style.css"; import { useState } from "react"; const navLinks = [ { name: "Register", href: "/register" }, { name: "Login", href: "/login" }, { name: "Forgot Password", href: "/forgot-password" }, ]; export default function OuterAuthLayout({ children }) { const pathname = usePathname(); const [input, setInput] = useState(""); return (
setInput(e.target.value)} />
{navLinks.map((link) => { const isActive = pathname.startsWith(link.href); return ( {link.name} ); })} {children}
); } ``` When we move to new route input will be same and wont be reset. **With templates** Just change the file name from layout.jsx to template.jsx and now input will be reset and nothing will be preserved. Some limitations though. If there is a route group(say named inner-auth) like this Structure ```text src/app (auth) (inner-auth) login password forgot-password template.jsx style.css page.jsx ``` In this case, states between `login` and `password` routes will be shared not with `forget-password` route though.   **Loading UI** - Till now different files like `page.jsx`, `layout.jsx`, `not-found.jsx` and `template.jsx` have been used. There is another one ie `loading.jsx`. Structure ```text src/app blog first second loading.jsx layout.jsx page.jsx page.jsx ``` In `src/app/blog/loading.jsx` ```jsx export default function LoadingBlog() { return (

Loading

); } ``` To test it, make sure that `src/app/blog/page.jsx` loads slower due to setTimeout. Make sure that layout.jsx wont load slow as first layout.jsx is loaded then loading.jsx contents then page.jsx. In `src/app/blog/page.jsx` ```jsx import Link from "next/link"; export const metadata = { title: { absolute: "blog", default: "blog", }, }; function promiseSetTimeOut(time) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, time); }); } export default async function Blog() { await promiseSetTimeOut(1000); return ( <>

Blog

Home ); } ```