back
May 9, 2026

Next.js App Router Cheatsheet

สรุปความรู้และข้อควรระวังเวลาใช้ Next.js App Router (ตั้งแต่เวอร์ชัน 13 เป็นต้นไป) ที่มักจะงงบ่อยๆ


Server Components vs Client Components

โดยค่าเริ่มต้น (Default) ทุก Component ใน App Router จะเป็น Server Component เสมอ

ใช้ Server Component เมื่อไหร่?

  • ต้องการ Fetch ข้อมูลจาก Database โดยตรง
  • ข้อมูลที่เป็นความลับ (API Keys, Tokens)
  • ต้องการลดขนาด JavaScript bundle ที่ส่งไปให้ผู้ใช้

ใช้ Client Component เมื่อไหร่? (ต้องใส่ "use client" ไว้บรรทัดแรกสุด)

  • เมื่อต้องใช้ State หรือ Lifecycle Hooks (useState, useEffect)
  • เมื่อต้องใช้ Event Listeners (onClick, onChange)
  • เมื่อต้องใช้ Browser APIs (window, document)

กฎเหล็ก: Client Component ไม่สามารถเรียกใช้ Server Component เป็นลูก (Child) ตรงๆ ได้ (เว้นแต่จะส่งผ่าน children props)


การ Fetch ข้อมูล และ Caching

Next.js มีการปรับปรุง fetch API ให้ทำการ Cache ข้อมูลโดยอัตโนมัติ

tsx
// 1. Cache ถาวร (เหมือน getStaticProps ใน Pages Router)
const res = await fetch("https://api.example.com/data", {
  cache: "force-cache",
})

// 2. ไม่ Cache เลย ขอข้อมูลใหม่ทุกครั้ง (เหมือน getServerSideProps)
const res = await fetch("https://api.example.com/data", { cache: "no-store" })

// 3. Revalidate (อัปเดตข้อมูล) ทุกๆ X วินาที (เหมือน ISR)
const res = await fetch("https://api.example.com/data", {
  next: { revalidate: 60 },
})

Route Handlers (API Routes)

ย้ายจาก pages/api/* มาเป็น app/api/route.ts

tsx
import { NextResponse } from "next/server"

export async function GET(request: Request) {
  // ดึง Search Params (เช่น /api/users?name=john)
  const { searchParams } = new URL(request.url)
  const name = searchParams.get("name")

  return NextResponse.json({ message: `Hello ${name}` })
}

export async function POST(request: Request) {
  const body = await request.json()
  return NextResponse.json({ status: "success", data: body })
}

โครงสร้างไฟล์พิเศษใน 1 โฟลเดอร์

ใน 1 โฟลเดอร์ (Route) เราสามารถมีไฟล์พิเศษพวกนี้ได้:

  • page.tsx - หน้าจอหลัก (ต้องมี)
  • layout.tsx - โครงสร้างที่แชร์ให้หน้าลูกๆ ใช้งานร่วมกัน
  • loading.tsx - หน้าจอตอนกำลังโหลดข้อมูล (ใช้ React Suspense เบื้องหลัง)
  • error.tsx - หน้าจอตอนเกิด Error (ต้องเป็น "use client")
  • not-found.tsx - หน้าจอ 404 ของ Route นั้นๆ

Server Actions

ไม่ต้องเขียน API Route เองอีกต่อไป สามารถให้ Form ทำงานฝั่ง Server ได้เลย

tsx
// app/actions.ts
"use server"
export async function createPost(formData: FormData) {
  const title = formData.get("title")
  // บันทึกลง Database
}

// app/page.tsx
import { createPost } from "./actions"

export default function Page() {
  return (
    <form action={createPost}>
      <input name="title" type="text" />
      <button type="submit">Submit</button>
    </form>
  )
}