Pages, Layouts และ Nested Routing
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”ใน App Router folder หนึ่งคือ route segment หนึ่ง page.tsx ทำให้ segment นั้นเข้าถึงเป็น URL ได้ ส่วน layout.tsx ห่อ segment นั้นพร้อม children ทุกตัว และยัง mount ค้างไว้ข้ามการ navigate
Folder = route segment
หัวข้อที่มีชื่อว่า “Folder = route segment”ทุก folder ใต้ app/ map ไปเป็น URL segment หนึ่ง segment จะกลายเป็น URL ที่เข้าถึงได้ก็ต่อเมื่อมี page.tsx อยู่ข้างใน
app/ layout.tsx // root layout (required) page.tsx // route: / dashboard/ layout.tsx // wraps /dashboard and its children page.tsx // route: /dashboard settings/ page.tsx // route: /dashboard/settingspage.tsx เป็น Server Component โดย default และ render UI เฉพาะของ segment นั้น
export default function DashboardPage() { return <h1>Dashboard</h1>}The required root layout
หัวข้อที่มีชื่อว่า “The required root layout”ทุกแอป App Router ต้องมี root layout หนึ่งตัว เป็น layout เดียวที่ render tag <html> และ <body> และต้อง render children เสมอ
// app/layout.tsx — the required root layoutexport default function RootLayout({ children,}: { children: React.ReactNode}) { return ( <html lang="en"> <body>{children}</body> </html> )}Nested layouts persist and compose
หัวข้อที่มีชื่อว่า “Nested layouts persist and compose”layout.tsx ห่อ segment ของตัวเองและ descendant ทั้งหมด nested layout compose จากนอกเข้าใน root ห่อ dashboard ห่อ settings จุดสำคัญคือ layout จะ persist ข้ามการ navigate เมื่อย้ายระหว่าง route พี่น้องกัน layout ที่ใช้ร่วมจะไม่ re-render ทำให้ state และตำแหน่ง scroll ถูกเก็บไว้
// app/dashboard/layout.tsx — persists across navigationexport default function DashboardLayout({ children,}: { children: React.ReactNode}) { return ( <section> <nav>{/* stays mounted, keeps scroll + local state */}</nav> <main>{children}</main> </section> )}loading.tsx and error.tsx
หัวข้อที่มีชื่อว่า “loading.tsx and error.tsx”ใส่ loading.tsx แล้ว Next.js จะห่อ segment ด้วย Suspense boundary ให้อัตโนมัติ fallback จะโชว์ทันทีระหว่างที่งานฝั่ง server ยัง stream เข้ามา
// app/dashboard/loading.tsx — automatic Suspense boundaryexport default function Loading() { return <p>Loading dashboard…</p>}ใส่ error.tsx แล้ว Next.js จะห่อ segment ด้วย error boundary ไฟล์นี้ต้องเป็น Client Component และรับ error พร้อมฟังก์ชัน reset ไว้ลอง render segment ใหม่
'use client' // error boundaries must be Client Components
export default function Error({ error, reset,}: { error: Error & { digest?: string } reset: () => void}) { return ( <div> <h2>Something went wrong</h2> <button onClick={() => reset()}>Try again</button> </div> )}graph TD R["app/layout.tsx (root, persists)"] --> D["dashboard/layout.tsx (persists)"] D --> P["dashboard/page.tsx"] D --> S["settings/page.tsx"]