Nested routes and layouts


การสร้างเส้นทางซ้อน

Next.js รองรับการสร้างเส้นทางซ้อน ทำให้คุณสามารถสร้างโครงสร้างหน้าได้อย่างยืดหยุ่นและง่ายดาย โดยการจัดไฟล์ในไดเรกทอรีซ้อนกัน

ตัวอย่าง

สมมติว่าเราต้องการสร้างหน้าบทความที่มีหมวดหมู่ และแต่ละหมวดหมู่มีหลายบทความ

โครงสร้างไดเรกทอรี

my-next-app/
├── pages/
│   ├── blog/
│   │   ├── index.js
│   │   ├── category/
│   │   │   └── [category].js
│   │   └── [id].js

URLs ที่สามารถเข้าถึงได้

  1. หน้าแรกของ Blog:

    • URL: http://localhost:3000/blog

    • ไฟล์ที่จัดการ: pages/blog/index.js

    • โค้ด:

      // pages/blog/index.js
      export default function Blog() {
        return <h1>Blog Home Page</h1>;
      }
  2. หน้าหมวดหมู่ใน Blog:

    • URL: http://localhost:3000/blog/category/[category]

    • ไฟล์ที่จัดการ: pages/blog/category/[category].js

    • ตัวอย่าง URL:

      • http://localhost:3000/blog/category/technology

      • http://localhost:3000/blog/category/lifestyle

    • โค้ด:

      // pages/blog/category/[category].js
      import { useRouter } from 'next/router';
      
      export default function Category() {
        const router = useRouter();
        const { category } = router.query;
      
        return <h1>Category: {category}</h1>;
      }
  3. หน้าบทความใน Blog:

    • URL: http://localhost:3000/blog/[id]

    • ไฟล์ที่จัดการ: pages/blog/[id].js

    • ตัวอย่าง URL:

      • http://localhost:3000/blog/123

      • http://localhost:3000/blog/456

    • โค้ด:

      // pages/blog/[id].js
      import { useRouter } from 'next/router';
      
      export default function Post() {
        const router = useRouter();
        const { id } = router.query;
      
        return <h1>Blog Post ID: {id}</h1>;
      }

การสร้าง Layout

Layout เป็น UI ที่ใช้ร่วมกันระหว่างหลายเส้นทาง เมื่อมีการนำทาง Layout จะรักษาสถานะ, ยังคงอินเทอร์แอคทีฟ และไม่ทำการเรนเดอร์ใหม่ Layouts ยังสามารถซ้อนได้

คุณสามารถกำหนด Layout ได้โดยการ export คอมโพเนนต์ React จากไฟล์ layout.js คอมโพเนนต์นี้ควรรับ children เป็น prop ซึ่งจะถูกแทนที่ด้วย Layout ลูก (ถ้ามี) หรือหน้าในระหว่างการเรนเดอร์

ตัวอย่างการใช้งาน Layout

ไฟล์ Layout สำหรับเส้นทาง /dashboard และ /dashboard/settings:

my-next-app/
├── pages/
│   ├── _app.js
│   ├── layout.js
│   ├── dashboard/
│   │   ├── layout.js
│   │   ├── index.js
│   │   └── settings.js

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      <nav></nav>
      {children}
    </section>
  );
}

Root Layout (จำเป็นต้องมี)

Root Layout ถูกกำหนดที่ระดับบนสุดของไดเรกทอรี app และใช้กับทุกเส้นทาง Layout นี้ต้องมีแท็ก html และ body เพื่อให้สามารถปรับแต่ง HTML เริ่มต้นที่ส่งกลับจากเซิร์ฟเวอร์ได้

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <main>{children}</main>
      </body>
    </html>
  );
}

การซ้อน Layouts

Layouts ในโฟลเดอร์จะถูกซ้อนกันตามโครงสร้างโฟลเดอร์โดยค่าเริ่มต้น ซึ่งหมายความว่า Layouts จะห่อหุ้ม Layout ลูกผ่าน children prop คุณสามารถซ้อน Layouts โดยการเพิ่มไฟล์ layout.js ภายในเส้นทางที่เฉพาะเจาะจง (โฟลเดอร์)

ตัวอย่างการซ้อน Layout สำหรับเส้นทาง /dashboard

my-next-app/
├── pages/
│   ├── _app.js
│   ├── layout.js
│   ├── dashboard/
│   │   ├── layout.js
│   │   ├── index.js
│   │   └── settings.js

จากตัวอย่าง ถ้าเราเราเปิดหน้าเพจของ dashboard Layout จะถูกแสดงผลจากของตัวเอง (dashboard/layout.js) และจาก Root Layout (pages/layout.js)

ข้อควรรู้

  • สามารถใช้ไฟล์ที่มีนามสกุล .js, .jsx, หรือ .tsx สำหรับ Layouts

  • เฉพาะ Root Layout เท่านั้นที่สามารถมีแท็ก <html> และ <body>

  • เมื่อมีการกำหนดทั้งไฟล์ layout.js และ page.js ในโฟลเดอร์เดียวกัน Layout จะห่อหุ้มหน้าเพจ

  • Layouts เป็น Server Components โดยค่าเริ่มต้น แต่สามารถตั้งค่าเป็น Client Component ได้

Last updated