ข้ามไปยังเนื้อหา

Server Actions คืออะไร

Server Action คือ async function ที่ mark ด้วย directive "use server" และรันบน server เท่านั้น เราเรียก action ตรง ๆ จาก <form> หรือจาก Client Component ได้เลยโดยไม่ต้องเขียน API route

เรา mark function ให้เป็น Server Action ได้สองแบบ แบบแรกใส่ "use server" ไว้บนสุดของ inline async function ภายใน Server Component แบบที่สองใส่ 'use server' ไว้บนสุดของทั้ง module file แล้วทุก export ในไฟล์นั้นจะกลายเป็น action

// app/page.tsx — an inline Server Action inside a Server Component
export default function Page() {
async function createTodo(formData: FormData) {
'use server'
const title = String(formData.get('title'))
await db.todo.create({ data: { title } })
}
return (
<form action={createTodo}>
<input name="title" />
<button type="submit">Add</button>
</form>
)
}

เมื่อหลาย component ต้องใช้ action เดียวกัน ให้ย้าย action ไปไว้ในไฟล์เฉพาะ ใส่ 'use server' หนึ่งครั้งบนสุด แล้วทุก export จะกลายเป็น action ที่เรียกได้ วิธีนี้รวม logic ของ mutation ไว้ที่เดียว และให้ Client Component import ไปใช้ได้

// app/actions.ts — every export here is a Server Action
'use server'
export async function createTodo(formData: FormData) {
const title = String(formData.get('title'))
await db.todo.create({ data: { title } })
}
export async function deleteTodo(id: string) {
await db.todo.delete({ where: { id } })
}

เราต่อ Server Action เข้ากับ form ตรง ๆ ด้วย <form action={createTodo}> แล้ว Next.js จะ post ข้อมูล form ไปที่ action บน server หรือจะ import action เข้าไปใน Client Component แล้วเรียกเหมือน function ปกติก็ได้ Next.js จะแปลง call นั้นเป็น network request ให้เอง

// app/todo-button.tsx — calling an action from a Client Component
'use client'
import { deleteTodo } from './actions'
export function DeleteButton({ id }: { id: string }) {
return <button onClick={() => deleteTodo(id)}>Delete</button>
}

Route Handler ใน route.ts คือ URL สาธารณะที่เราออกแบบ ต่อ และ fetch เอง ส่วน Server Action คือ function ที่เราเรียกตรง ๆ Next.js สร้าง endpoint และ network call ให้ และรองรับ progressive enhancement ผ่าน form เลือก Route Handler เมื่อต้องการ public API หรือ webhook จริง ๆ และเลือก Server Action สำหรับ flow ของ form และ mutation ภายใน app ของเราเอง

graph LR
  A["form or Client Component"] -->|"calls action"| B["Next.js generated endpoint"]
  B -->|"runs on server only"| C["Server Action function"]
  C -->|"reads or writes"| D["Database"]
How a Server Action call reaches the server
What does the "use server" directive mark a function as?
What happens when you add 'use server' at the top of a module file?
How do you call a Server Action from a Client Component?
When should you reach for a Route Handler instead of a Server Action?