CHAPTER 2
ROUTING NEXTJS
Dasar-Dasar Routing
Routing adalah kerangka utama dari setiap aplikasi. Materi berikut akan memperkenalkan
konsep dasar routing untuk web dan bagaimana mengelola routing dalam [Link].
Terminologi
Berikut adalah beberapa istilah yang akan sering digunakan dalam dokumentasi:
Terminologi untuk Pohon Komponen:
● Pohon (Tree): Konvensi untuk memvisualisasikan struktur hierarkis, seperti pohon
komponen dengan komponen induk dan anak, struktur folder, dll.
● Sub Pohon (Subtree): Bagian dari pohon yang dimulai dari akar baru (root) dan
berakhir pada daun (leaf).
● Akar (Root): Node pertama dalam pohon atau subpohon, seperti layout root.
● Daun (Leaf): Node dalam subpohon yang tidak memiliki anak, seperti segmen
terakhir dalam path URL.
Terminologi untuk Anatomi URL:
● Segmen URL: Bagian dari path URL yang dibatasi oleh garis miring.
● Path URL: Bagian dari URL yang muncul setelah domain (terdiri dari segmen-
segmen).
App Router
Mulai versi 13, [Link] memperkenalkan App Router baru yang dibangun di atas React
Server Components. App Router ini mendukung layout yang dapat dibagikan, routing
bersarang, status loading, penanganan error, dan lainnya.
App Router bekerja di direktori baru bernama app. Direktori app ini bekerja berdampingan
dengan direktori pages, sehingga memungkinkan pemanggilan halaman secara bersarang.
App Router memiliki prioritas lebih tinggi dibandingkan dengan Pages Router. Rute di
antara direktori tidak boleh mengarah ke path URL yang sama, karena ini akan
menyebabkan error saat build untuk mencegah konflik.
Direktori App [Link]
Secara default, komponen di dalam direktori app adalah React Server Components namun
kita juga bisa menggunakan Client Components.
[Link] menggunakan router berbasis sistem file di mana:
● Folder digunakan untuk mendefinisikan rute. Sebuah rute adalah jalur tunggal dari
folder yang terstruktur secara berlapis, mengikuti hirarki sistem file dari folder root
hingga folder leaf terakhir yang berisi file [Link]. Lihat Mendefinisikan Rute.
● File digunakan untuk membuat UI yang ditampilkan untuk segmen rute. Lihat file-file
khusus.
Segmen Rute Setiap folder dalam sebuah rute mewakili sebuah segmen rute. Setiap
segmen rute dipetakan ke segmen yang sesuai dalam jalur URL.
Hierarki Komponen Komponen React yang didefinisikan dalam file-file khusus dari sebuah
segmen rute dirender dalam hierarki tertentu:
● [Link]
● [Link]
● [Link] (React error boundary)
● [Link] (React suspense boundary)
● [Link] (React error boundary)
● [Link] atau nested [Link]
Dalam sebuah rute bersarang, komponen-komponen dari sebuah segmen akan disusun di
dalam komponen-komponen dari segmen induknya.
Colocation Selain file-file khusus, kita memiliki opsi untuk menempatkan file-file kita sendiri
(misalnya, komponen, gaya, pengujian, dll.) di dalam folder di direktori app.
Hal ini dimungkinkan karena meskipun folder mendefinisikan rute, hanya konten yang
dikembalikan oleh [Link] atau [Link] yang dapat diakses secara publik.
Pembuatan Component dan Pages
System Requirements:
[Link] 18.17 or later.
macOS, Windows (including WSL), and Linux are supported.
Langkah-langkah praktikum:
Pembuatan Header
1. Masih menggunakan project personal web profile yang telah dibuat pada Chapter 1.
Buat file baru bernama [Link] di dalam folder components (jika belum ada,
buatlah folder ini di root proyek sejajar dengan folder app).
2. Tambahkan kode program berikut untuk membuat desain header
import Link from 'next/link';
const Header = () => {
return (
<header className="bg-brown text-soft-brown py-4 sticky top-0">
<nav className="container mx-auto flex justify-between items-center">
<Link href="/" className="text-2xl font-bold">
Nicole
</Link>
<ul className="flex space-x-4">
<li>
<Link href="/" className="hover:text-white">
Home
</Link>
</li>
<li>
<Link href="/portofolio" className="hover:text-white">
Portfolio
</Link>
</li>
<li>
<Link href="/blog" className="hover:text-white">
Blog
</Link>
</li>
</ul>
</nav>
</header>
);
};
export default Header;
3. Setelah itu, import dan implementasikan header pada [Link] (text yang di bold)
import type { Metadata } from "next";
import { Open_Sans } from "next/font/google";
import "./[Link]";
{/* 👇 Import Header pada Layout */}
import Header from '../components/header';
const openSans = Open_Sans({
subsets: ['latin'],
display: 'swap',
});
export const metadata: Metadata = {
title: "My Profile",
description: "Generated by create next app"
};
export default function RootLayout({
children,
}: Readonly<{
children: [Link];
}>) {
return (
<html lang="en">
<body className={[Link]}>
{/* 👇 Tambahkan Header pada Layout */}
<Header />
<div className="bg-home bg-no-repeat bg-cover">
<div className="bg-brown w-screen">
{children}
</div>
</div>
</body>
</html>
);
}
Hasilnya adalah sebagai berikut:
Pembuatan Halaman Portofolio
1. Buatlah Folder bernama data pada folder root dan file [Link] untuk
menyimpan array portofolio seperti berikut
2. Contoh data portofolio adalah sebagai berikut
export interface PortofolioItem {
id: number;
name: string;
image: string;
description: string;
category: string
}
export const arrayPorto: PortofolioItem[] = [
{
id: 1,
name: "Kupa - Food Delivery App",
image:
"[Link]
description: "Kupa is a Premium Food Delivery App UI Kit consisting of
80+ pixel-perfect screens and easy to use in Figma.",
category: "mobile"
},
{
id: 2,
name: "Bakery shopping application",
image:
"[Link]
description: "UI/UX,Web Design,Figma,Adobe Illustrator,Adobe XD,Adobe
Photoshop.",
category: "mobile"
},
{
id: 3,
name: "Echofy – Environment, Ecology & Solar Energy",
image:
"[Link]
description: "Echofy Nature HTML Template is created to help you make
world’s environment cleaner and save the nature.",
category: "website"
},
{
id: 4,
name: "Social Media Marketing Agency",
image:
"[Link]
description: "Socialy is a modern Social Media Marketing Agency
Elementor Template Kit that perfect for creating a website for Digital
Marketing Agency that specialized in Social Media Marketing.",
category: "website"
},
]
3. Pada folder app buat folder baru bernama portofolio kemudian tambahkan file
[Link]
import Image from "next/image";
import Link from "next/link";
import { arrayPorto } from '../../data/portofolio';
export default function Portofolio() {
return (
<main className="container mx-auto">
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24
lg:max-w-7xl lg:px-8 h-screen">
<h2 className="text-2xl font-bold tracking-tight text-center
text-soft-brown">My Portofolio</h2>
<div className="mt-6 grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-
cols-2 lg:grid-cols-4 xl:gap-x-8">
{[Link]((porto, index) => (
<div key={index} className="group relative">
<Link href={`/portofolio/${[Link]}`}>
<div className="aspect-h-1 aspect-w-1 w-full overflow-
hidden rounded-md bg-gray-200 lg:aspect-none group-hover:opacity-75 lg:h-
80">
<Image
alt={[Link]}
src={[Link]}
width={100}
height={100}
unoptimized
className="h-full w-full object-cover object-
center lg:h-full lg:w-full"
/>
</div>
<div className="mt-4 flex justify-between">
<div>
<h3 className="text-sm text-soft-
brown">{[Link]}</h3>
<p className="mt-1 text-sm text-gray-
300">{[Link]}</p>
</div>
</div>
</Link>
</div>
))}
</div>
</div>
</main>
);
}
Halaman portofolio akan menampilkan array portofolio yang sudah disiapkan
pada folder data yang terdiri dari rincian data berikut:
id: number;
name: string;
image: string;
description: string;
category: string;
Gambar ditampilkan menggunakan link yang telah dibahas pada Chapter 1
4. Hasil pembuatan halaman portofolio adalah sebagai berikut:
Pembuatan Halaman Blog
1. Pada Folder data pada folder root dan file [Link] untuk menyimpan array blog
2. Contoh data blog adalah sebagai berikut
export interface BlogPost {
id: number;
title: string;
slug: string;
date: string;
excerpt: string;
content: string;
}
export const blogPosts: BlogPost[] = [
{
id: 1,
title: "Getting Started with [Link]",
slug: "getting-started-with-nextjs",
date: "2024-03-15",
excerpt: "Learn the basics of [Link] and start building your first
app.",
content: `
[Link] is a powerful React framework that makes it easy to build
server-side rendered and statically generated web applications.
Key Features of [Link]:
- Server-Side Rendering (SSR)
- Static Site Generation (SSG)
- File-based Routing
- API Routes
In this tutorial, we'll walk through the process of setting up a
[Link] project and creating your first pages.
`
},
{
id: 2,
title: "CSS Tips and Tricks",
slug: "css-tips-and-tricks",
date: "2024-03-20",
excerpt: "Improve your CSS skills with these handy tips and tricks.",
content: `
CSS is gaining powers with recent web evolution. And it is very clever
with tricks that were long existing or that
have emerged. Perhaps tricks shared here will school you with CSS
tricks from the depths you were yet to explore.
1. Draw a triangle using border
2. Interchange background of an element
3. Center an element
4. Pill 💊 shape button
5. Easily add beautiful loading indicator to your website
6. Easy dark or light mode
7. Truncate overflowing text with an ellipsis(...)
8. Truncate long text to a number of lines
9. Stop overworking yourself writing top, right, bottom, left
10. Serve optimized images
`
},
];
3. Pada folder app buat folder baru bernama blog kemudian tambahkan file [Link]
import Link from 'next/link';
import { blogPosts } from '../../data/blog';
export default function BlogPage() {
return (
<main className="container mx-auto">
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24
lg:max-w-7xl lg:px-8 h-screen">
<h1 className="text-3xl font-bold mb-8 text-soft-brown">Blog
Posts</h1>
<div className="grid gap-6">
{[Link]((post) => (
<div key={[Link]} className="border border-gray-200 p-4
rounded-lg">
<Link href={`/blog/${[Link]}`}>
<h2 className="text-xl font-semibold mb-2 text-soft-
brown hover:underline">
{[Link]}
</h2>
</Link>
<p className="text-white text-sm font-semibold mb-
2">{[Link]}</p>
<p>{[Link]}</p>
</div>
))}
</div>
</div>
</main>
);
}
Halaman blog akan menampilkan array blog yang sudah disiapkan pada
folder data yang terdiri dari rincian data berikut:
id: number;
title: string;
slug: string;
date: string;
excerpt: string;
content: string;
Slug dan detail konten akan dijelaskan pada bagian berikutnya
4. Hasil pembuatan halaman blog adalah sebagai berikut:
Dynamic Route
Routing dinamis digunakan untuk membuat URL yang berubah berdasarkan data yang
diberikan, seperti ID pengguna atau nama artikel. Hal ini memanfaatkan tanda kurung []
untuk menangkap bagian dinamis dari URL. Pada materi ini, kita akan mempraktekkan
penggunaan routing yang meliputi: 1) Query, 2) Param, dan 3) Slug.
Routing dengan Query
Query adalah pasangan nilai kunci yang disertakan dalam URL setelah tanda tanya ?.
Query parameters digunakan untuk menambahkan informasi opsional ke URL, seperti filter,
pencarian, atau pengurutan tanpa mengubah struktur URL utama. Dalam pembuatan routing
dengan query parameter, kita akan menambahkan filter pada halaman portofolio agar bisa
menampilkan data portofolio sesuai kategori
1. pada file [Link] di dalam folder portofolio tambahkan parameter seperti berikut
sebelum:
export default function Portofolio()
sesudah:
export default function Portofolio({ searchParams }: { searchParams: {
category?: string } })
2. Sebelum fungsi return, tambahkan variable category dan fungsi filter agar data
portofolio yang ditampilkan sesuai dengan category yang dipilih
const category = [Link];
const filteredPorto = category
? [Link](porto => [Link]() ===
[Link]())
: arrayPorto;
3. Di bawah tag h2 judul My Portofolio tambahkan link untuk mengupdate parameter
query sesuai pilihan kategori yaitu: 1) website, dan 2) mobile.
{/* Category Filter */}
<div className="mt-4 mb-6 flex justify-center space-x-4">
<Link href="/portofolio" className={`text-soft-brown ${!category ?
'font-bold' : ''}`}>All</Link>
<Link href="/portofolio?category=website" className={`text-soft-brown
${category === 'website' ? 'font-bold' : ''}`}>Web</Link>
<Link href="/portofolio?category=mobile" className={`text-soft-brown $
{category === 'mobile' ? 'font-bold' : ''}`}>Mobile</Link>
</div>
4. Ubah function map yang sebelumnya arrayPorto menjadi filteredPorto seperti
berikut
sebelum
{[Link]((porto, index) => ( … )
sesudah
{[Link]((porto, index) => ( … )
5. Hasil jika filter menampilkan semua category
6. Hasil jika filter menampilkan category Website
7. Hasil jika filter menampilkan category Mobile
Routing dengan Parameters
Param (parameter) digunakan untuk menangkap nilai dinamis dalam URL, biasanya
digunakan untuk mengakses halaman berdasarkan suatu ID atau identifier lain yang bersifat
unik. Pada materi ini, kita akan menampilkan detail portofolio sesuai dengan data id.
halaman akan secara dinamis menampilkan halaman portofolio sesuai detail id yang dipilih
1. Tambahkan folder bernama [id] di dalam folder portofolio seperti berikut
2. pada [Link] di dalam folder [id] kita akan menampilkan detail portofolio sebagai
berikut:
import Link from 'next/link';
import Image from 'next/image';
import { arrayPorto } from '../../../data/portofolio';
type Params = {
id: string;
}
export default function ProjectDetail({ params }: { params: Params }) {
const { id } = params;
const porto = [Link](p => [Link] === parseInt(id));
if (!porto) return <div>Project not found</div>;
return (
<div className="container mx-auto p-4">
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24
lg:max-w-7xl lg:px-8">
<Link href="/portofolio" className="inline-block mb-6 text-soft-
brown hover:underline">
← Back to Portfolio
</Link>
<p className='font-semibold text-sm text-soft-
brown'>{[Link]}</p>
<h1 className="text-2xl font-bold text-white">{[Link]}</h1>
<p className="mb-4">{[Link]}</p>
<Image
alt={[Link]}
src={[Link]}
width={500}
height={50}
className=""
unoptimized />
</div>
</div>
);
}
3. Jika salah satu portofolio di klik, halaman akan diarahkan pada detail portofolio
sesuai id yang dipilih seperti berikut
Routing dengan Slug
Slug adalah bagian dinamis dari URL yang biasanya berbentuk lebih SEO-friendly dan
deskriptif, sering kali digunakan dalam blog, artikel, atau halaman proyek. Slug sering kali
berupa string deskriptif, bukan sekadar angka atau ID. Pada materi ini, kita akan
menerapkan slug pada halaman Blog untuk menampilkan detail blog.
1. Tambahkan folder bernama [slug] di dalam folder blog seperti berikut
4. pada [Link] di dalam folder [slug] kita akan menampilkan detail slug sebagai
berikut:
import { blogPosts } from '../../../data/blog';
import Link from 'next/link';
import ReactMarkdown from 'react-markdown';
interface Params {
slug: string;
}
export default function BlogPostPage({ params }: { params: Params }) {
const post = [Link](post => [Link] === [Link]);
if (!post) {
return <div>Post not found</div>;
}
return (
<div className="container mx-auto">
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24
lg:max-w-7xl lg:px-8 h-screen">
<Link href="/blog" className="inline-block mb-6 text-soft-brown
hover:underline">
← Back to Blog
</Link>
<h1 className="text-3xl font-bold mb-4 text-soft-
brown">{[Link]}</h1>
<p className="text-white text-sm font-bold mb-4">{[Link]}</p>
<ReactMarkdown>{[Link]}</ReactMarkdown>
</div>
</div>
);
}
5. Jika salah satu blog di klik, halaman akan diarahkan pada detail blog sesuai slug
yang dipilih seperti berikut
Tugas
1. Tambahkan 2 daftar blog pada data dan tambahkan category
2. Buatlah filter category untuk menu Blog agar bisa menampilkan blog berdasarkan
kategori tertentu