Lompat ke konten
dokumentasi.id
Commit 9a47d33
v2
Star3,4 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

6

Halaman, Error Boundary, dan Endpoint API

src/app pada commit ini berisi lima berkas yang bersama-sama membentuk permukaan aplikasi: halaman /, katalog /components, error.tsx sebagai error boundary, not-found.tsx sebagai halaman rute tak dikenal, dan Route Handler api/hello. Empat berkas pertama berupa komponen React, yang terakhir tidak me-render UI sama sekali.

Peta rute dan jenis komponen

Setiap rute dipetakan langsung oleh nama berkas di dalam src/app. Tabel berikut mencatat jenis komponen dan keluaran yang dihasilkan tiap berkas.

URLBerkasJenisKeluaranRujukan
/src/app/page.tsxClient Component, ditandai 'use client'halaman sambutan dan tautan ke /componentssrc/app/page.tsx:1-4
/componentssrc/app/components/page.tsxClient Component yang menyimpan mode dan color di React.useStatekatalog komponen pratinjausrc/app/components/page.tsx:27-32
/api/hellosrc/app/api/hello/route.tsRoute Handler yang hanya mengekspor GETNextResponse.json({ hello: 'Next.js' })src/app/api/hello/route.ts:1-5
error segmensrc/app/error.tsxClient Component, wajibteks "Oops, something went wrong!" dan tombol resetsrc/app/error.tsx:1-18
rute tak dikenalsrc/app/not-found.tsxServer Component yang mengekspor metadatateks "Page Not Found"src/app/not-found.tsx:1-7

Kedua halaman yang dilihat pengguna berjalan di client. src/app/page.tsx bahkan mengimpor @/lib/env di baris keempat, sehingga envVariables.parse(process.env) ikut dijalankan saat modul halaman dimuat. Rincian validasi itu ada di Utilitas, Logger, dan Environment.

Di src/app tidak ada loading.tsx, template.tsx, maupun global-error.tsx. Konsekuensinya error.tsx hanya menangkap error dari segmen di bawah RootLayout, bukan error yang dilempar RootLayout sendiri. Susunan layout dan metadata dibahas di App Router, Layout, dan Metadata.

Halaman utama /

HomePage menyusun satu <main> berisi satu <section className='bg-white'> dengan pembungkus layout relative flex min-h-screen flex-col items-center justify-center py-12 text-center src/app/page.tsx:24-43. Isinya berurutan: komponen Logo hasil impor ~/svg/Logo.svg, <h1> berisi "Next.js + Tailwind CSS + TypeScript Starter", ArrowLink ke repository GitHub, dan ButtonLink dengan href='/components' serta variant='light' yang menjadi pintu masuk ke katalog. Transformasi *.svg menjadi komponen React diatur @svgr/webpack, yang dibahas di Konfigurasi Build dan Alat Pengembangan.

Dua tautan keluar melengkapi halaman. Tombol deploy Vercel ditulis sebagai <img> biasa di dalam UnstyledLink dengan width='92' dan height='32', dan baris eslint-disable-next-line @next/next/no-img-element menandai penyimpangan itu src/app/page.tsx:45-56. Footer memakai new Date().getFullYear() dan UnderlineLink ke https://theodorusclarence.com?ref=tsnextstarter src/app/page.tsx:58-63. Karena halaman ini client component, tahun pada footer dihitung di browser, bukan saat build.

Katalog pratinjau /components

ComponentPage menyimpan dua state: mode bertipe 'dark' | 'light' dengan nilai awal 'light', dan color bertipe turunan colorList dengan nilai awal 'sky' src/app/components/page.tsx:27-32. colorList sendiri berisi 22 nama warna Tailwind, dari 'slate' sampai 'rose', dan ditutup as const supaya tipenya menyempit src/app/components/page.tsx:438-461.

Navigasi keluar dari katalog ada dua arah. ArrowLink direction='left' href='/' mengembalikan pengunjung ke halaman utama src/app/components/page.tsx:48-50, sedangkan ButtonLink href='/404' menawarkan halaman 404 kustom src/app/components/page.tsx:402-408. Isi tiap komponen yang dipamerkan dijelaskan di Katalog Komponen Pratinjau.

⚠️ ButtonLink href='/404' tidak punya berkas rute yang cocok. src/app tidak berisi direktori 404 dan repository ini tidak punya direktori src/pages, sehingga request ke /404 dilayani not-found.tsx — halaman yang sama dengan rute tak dikenal lain. Tautan itu menampilkan "Page Not Found", bukan halaman kustom tersendiri src/app/not-found.tsx:9-23.

Endpoint /api/hello

Route Handler ini adalah satu-satunya endpoint di repository. Berkasnya hanya berisi lima baris.

AspekNilaiRujukan
Berkas rutesrc/app/api/hello/route.tssrc/app/api/hello/route.ts:1-5
Metode yang dieksporGET, sebagai async function tanpa parametersrc/app/api/hello/route.ts:3-5
Nilai balikNextResponse.json({ hello: 'Next.js' })src/app/api/hello/route.ts:4
Pemakai di dalam repositorytidak ada, tidak satu pun berkas lain memanggil /api/hellosrc/app/api/hello/route.ts:1-5

Karena hanya GET yang diekspor, endpoint ini tidak menyediakan POST, PUT, atau DELETE. Tidak ada autentikasi, pembacaan request, maupun cache khusus; response JSON dikirim apa adanya. Endpoint ini berfungsi sebagai contoh bentuk Route Handler, bukan sebagai backend aplikasi.

Perpindahan antara halaman normal, error boundary, dan halaman tidak ditemukan

Diagram berikut merangkum transisi yang benar-benar dibuka oleh kode: tautan antahalaman, rute yang tidak terdaftar, dan reset dari error boundary.

stateDiagram-v2
    [*] --> Home
    Home --> Components: ButtonLink href="/components"
    Components --> Home: ArrowLink direction="left"
    Home --> NotFound: rute tidak terdaftar
    Components --> NotFound: ButtonLink href="/404"
    NotFound --> Home: a href="/"
    Home --> ErrorBoundary: render melempar Error
    Components --> ErrorBoundary: render melempar Error
    ErrorBoundary --> Home: reset() dari TextButton
    classDef ok fill:#2d7d46,color:#fff
    classDef bad fill:#dc2626,color:#fff
    classDef warn fill:#f59e0b,color:#000
    class Home,Components ok
    class ErrorBoundary bad
    class NotFound warn
%% fig: Transisi halaman normal, error boundary, dan 404
%% desc: Dua halaman client dapat saling bertukar lewat tautan, berakhir di not-found.tsx saat rute tidak ada, atau masuk ke error.tsx yang menyediakan reset.
Fig. 1: Transisi halaman normal, error boundary, dan 404Dua halaman client dapat saling bertukar lewat tautan, berakhir di not-found.tsx saat rute tidak ada, atau masuk ke error.tsx yang menyediakan reset.

Kedua penanganan kegagalan memakai ikon dan gaya yang sama, tetapi kontraknya berbeda.

Aspeksrc/app/error.tsxsrc/app/not-found.tsx
Direktif'use client' dengan komentar // Error components must be Client Components src/app/error.tsx:1tanpa direktif, jadi Server Component src/app/not-found.tsx:1-7
Propserror: Error & { digest?: string } dan reset: () => void src/app/error.tsx:8-14tidak menerima props src/app/not-found.tsx:9
Efek sampingconsole.error(error) di dalam React.useEffect dengan dependensi [error] src/app/error.tsx:15-18tidak ada
Aksi pemulihanTextButton variant='basic' onClick={reset} berlabel "Try again" src/app/error.tsx:31-33tautan <a href='/'> berlabel "Back to home" src/app/not-found.tsx:19
Metadatatidak diekspormetadata dengan title: 'Not Found' src/app/not-found.tsx:5-7

Tombol "Try again" pada error boundary adalah TextButton, yang me-render <button type='button'> sehingga reset terpasang sebagai handler onClick biasa src/components/buttons/TextButton.tsx:22-26. Judul 'Not Found' dari not-found.tsx masuk ke template %s | ${siteConfig.title} milik RootLayout, jadi tab browser menampilkan "Not Found" diikuti judul situs src/app/layout.tsx:12-17. Sebaliknya error.tsx tidak mengatur judul, karena komponen error tidak boleh mengekspor metadata.