Dynamic Segments และ Route Groups
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”folder ที่อยู่ใน bracket เปลี่ยนส่วนของ URL ให้เป็น param ที่เราอ่านจาก Promise ส่วน folder ในวงเล็บและที่ขึ้นต้นด้วย underscore จัดโครงสร้าง file tree ใหม่โดยไม่แตะ URL
Dynamic segments read from a Promise
หัวข้อที่มีชื่อว่า “Dynamic segments read from a Promise”folder ชื่อ [id] จับ URL ส่วนหนึ่งมาเป็น param ใน Next.js ปัจจุบัน params เป็น Promise เราจึงต้อง await ก่อนใช้ searchParams ก็เป็นแบบเดียวกัน
export default async function Post({ params, searchParams,}: { params: Promise<{ id: string }> searchParams: Promise<{ [key: string]: string | string[] | undefined }>}) { const { id } = await params const { sort } = await searchParams return <article>Post {id} sorted by {sort}</article>}Catch-all and optional catch-all
หัวข้อที่มีชื่อว่า “Catch-all and optional catch-all”ใช้ [...slug] จับหลาย segment มาเป็น array ใช้ [[...slug]] เพื่อทำให้ segment เป็น optional เพื่อให้ route แม่ match ได้ด้วยแม้ไม่มี segment ต่อท้าย
app/ docs/ [...slug]/page.tsx // matches /docs/a and /docs/a/b/c shop/ [[...slug]]/page.tsx // matches /shop AND /shop/a/bexport default async function Docs({ params,}: { params: Promise<{ slug: string[] }>}) { const { slug } = await params return <h1>{slug.join(' / ')}</h1>}generateStaticParams prerenders dynamic routes
หัวข้อที่มีชื่อว่า “generateStaticParams prerenders dynamic routes”ใช้ export generateStaticParams เพื่อบอก Next.js ว่าจะ prerender param ค่าไหนบ้างตอน build แต่ละ object ที่ return จะกลายเป็นหนึ่ง page ที่ generate แบบ static
export function generateStaticParams() { return [{ id: '1' }, { id: '2' }, { id: '3' }]}Route groups and private folders
หัวข้อที่มีชื่อว่า “Route groups and private folders”folder ในวงเล็บอย่าง (marketing) คือ route group ใช้จัดระเบียบไฟล์และถือ shared layout ของตัวเองได้ แต่ชื่อโฟลเดอร์จะถูกตัดออกจาก URL ส่วน folder ที่ขึ้นต้นด้วย underscore อย่าง _components เป็น private folder ที่ opt out จาก routing ทั้งหมด
app/ (marketing)/ layout.tsx // layout for marketing pages only about/page.tsx // URL is /about, NOT /marketing/about (shop)/ cart/page.tsx // URL is /cart _components/ // private, never a route Button.tsxgraph TD A["[id] dynamic segment"] --> U1["changes URL: /blog/42"] B["[...slug] catch-all"] --> U2["changes URL: /docs/a/b"] C["(marketing) route group"] --> U3["no URL change"] D["_components private"] --> U4["not routable"]