useActionState เป็น Hook ตัวใหม่ใน React 19 ที่ช่วยให้การจัดการ state ที่เกี่ยวข้องกับฟอร์มเป็นเรื่องง่ายขึ้นมาก โดยมันช่วยลดความซับซ้อนของการจัดการฟังก์ชัน onSubmit ในฟอร์มต่าง ๆ โดยตรง
ใน React 18 เราอาจเคยเห็น Hook ที่ชื่อ useFormState ซึ่งเป็นเวอร์ชันทดลอง แต่ใน React 19 ชื่อนั้นถูกเปลี่ยนมาเป็น useActionState พร้อมฟีเจอร์ที่สมบูรณ์
What is useActionState
useActionState คือ Hook ที่ออกแบบมาให้ช่วยจัด state ของ Form หลังจากการดำเนินการ (action) เสร็จสมบูรณ์
“useActionState is a Hook that allows you to update state based on the result of a form action.”
หรือพูดง่าย ๆ มันคือเครื่องมือที่ช่วยจัดการ state โดยพิจารณาจากผลลัพธ์ของ action ที่ถูกส่งจากฟอร์ม
โดยหน้าตาของ hook เวลาเราเรียกใช้งาน จะเป็นแบบนี้
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);Parameters
โดยสิ่งที่ต้องส่งให้ hook คือ function และ initial state ส่วน permalink คือ optional
fnคือ function ที่ใช้ในการอัพเดท stateinitialStateคือค่าเริ่มต้นของ statepermalinkคือ URL ใช้สำหรับเก็บ state ระหว่างหน้าต่าง ๆ (ไม่บังคับใส่)
Return Value
โดยสิ่งที่ได้กลับมาหลังจาก เรียกใช้งาน ก็จะมี
stateคือ ค่าปัจจุบันที่ return จาก useActionStateformActionคือ function ที่ต้องผูกกับ action ของฟอร์มisPendingคือ สถานะของการส่ง form อยู่ในระหว่างรอการตอบรับ ใช้สำหรับทำ loading ตอน submit form ได้
ตัวอย่างการใช้งาน
1. Counter Form
ฟอร์มตัวอย่างที่เพิ่มค่าตัวเลขในทุกครั้งที่กดปุ่ม Submit
import { useActionState } from "react";
async function increment(previousState, formData) {
return previousState + 1;
}
function CounterForm() {
const [state, formAction] = useActionState(increment, 0);
return (
<form action={formAction}>
<p>Counter: {state}</p>
<button type="submit">Increment</button>
</form>
);
}2. แสดง Error Message จากการ Submit
ตัวอย่างนี้แสดงการส่งข้อมูลไปยัง action เพื่อตรวจสอบว่าการเพิ่มสินค้าลงในตะกร้าสำเร็จหรือไม่
mport { useActionState } from "react";
import { addToCart } from "./actions.js";
function AddToCartForm({ itemID, itemTitle }) {
const [message, formAction] = useActionState(addToCart, null);
return (
<form action={formAction}>
<h2>{itemTitle}</h2>
<input type="hidden" name="itemID" value={itemID} />
<button type="submit">Add to Cart</button>
{message && <p className="error">{message}</p>}
</form>
);
}function addToCart
//action.js
"use server";
export async function addToCart(prevState, queryData) {
const itemID = queryData.get("itemID");
if (itemID === "1") {
return "Added to cart";
} else {
return "Couldn't add to cart: the item is sold out.";
}
}3. Preserving Form State Across Pages
กรณีที่ต้องการให้ state ของฟอร์มถูกบันทึกไว้ระหว่างการเปลี่ยนหน้า เช่น ในตัวอย่างนี้คือ ฟอร์ม Feedback
import { useActionState } from "react";
import { submitFeedback } from "./actions.js";
function FeedbackForm() {
const [feedback, formAction] = useActionState(
submitFeedback,
"",
"/feedback",
);
return (
<form action={formAction}>
<textarea name="feedback" placeholder="Your feedback" />
<button type="submit">Submit</button>
<p>{feedback}</p>
</form>
);
}ประโยชน์ของใช้ useActionState
- ลด Boilerplate Code เพราะไม่ต้องเขียนฟังก์ชัน onSubmit หรือ useState ซ้ำ ๆ
- สะดวกในการจัดการ Loading State เพราะมีตัวแปร isPending ช่วยจัดการสถานะการโหลดได้ง่าย
- สามารถแชร์ state ระหว่างหน้าได้ โดยการใช้ permalink เพื่อคงค่าของฟอร์มไว้ในหลายหน้า