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

Actions

การจะเรียก server logic จาก client แบบเดิม คุณต้องเขียน endpoint, คิด URL, fetch() เอง, stringify body, เดา type ของ response และ validate input ด้วยมือบน server Actions ยุบทั้งหมดนั้นเหลือ function ที่ typed ตัวเดียว: define บน server แล้วเรียกจาก client ด้วย type-safety เต็มและ validation อัตโนมัติ

Action อยู่ใน src/actions/index.ts export เป็น object ชื่อ server แต่ละตัวคือ defineAction ที่มี schema input (Zod) และ handler:

src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
createComment: defineAction({
input: z.object({
postId: z.string(),
body: z.string().min(1).max(2000),
}),
handler: async (input, context) => {
// input is fully typed and already validated against the schema.
const comment = await db.comments.create({
postId: input.postId,
body: input.body,
userId: context.locals.user?.id, // per-request data from middleware
});
return comment; // the return type flows to the client
},
}),
};

สองอย่างเป็นอัตโนมัติ: input ถูก validate กับ Zod schema ก่อน handler รัน และ return type ของ handler ถูก infer ไปจนถึงผู้เรียก — ไม่ต้อง type response ด้วยมือ

ฝั่ง client ให้ import actions จาก astro:actions แล้วเรียกใช้ ทุกการเรียก return { data, error } — Astro ไม่ throw ข้าม boundary:

import { actions, isInputError } from 'astro:actions';
const { data, error } = await actions.createComment({
postId: '42',
body: 'Nice post!',
});
if (isInputError(error)) {
// Validation failed — error.fields has per-field messages.
console.log(error.fields.body);
} else if (data) {
console.log('Created comment', data.id); // data is typed
}
sequenceDiagram
  participant C as Client
  participant A as Astro Action
  participant H as handler
  C->>A: actions.createComment(input)
  A->>A: validate input against Zod schema
  A->>H: run handler(input, context)
  H-->>A: return value (typed)
  A-->>C: { data, error }
การเรียกจาก client รัน handler ที่ validate แล้ว

Action เชื่อมกับ HTML <form> ตรง ๆ ได้ด้วยการส่ง action.name — ทำงานเป็น form POST ปกติแม้ JavaScript ยังไม่โหลด แล้วอัปเกรดเป็น client call เมื่อ hydrate นี่คือ progressive enhancement: form submit ได้ทั้งสองทาง

---
import { actions } from 'astro:actions';
---
<form method="POST" action={actions.createComment}>
<input type="hidden" name="postId" value="42" />
<textarea name="body"></textarea>
<button type="submit">Comment</button>
</form>

คุณยังเรียก action จาก component script ได้ด้วย Astro.callAction(actions.createComment, input) เมื่อต้องการผลตอน server render handler ที่ validate แล้วตัวเดียวกันจะรันในทุกกรณี

define action ที่ไหน และแต่ละตัวต้องมีอะไร?
input ของ action เกิดอะไรก่อน handler รัน?
การเรียก action จาก client return อะไร?
คุณได้อะไรจากการเชื่อม action กับ `<form action={actions.name}>`?