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 เพื่อคงค่าของฟอร์มไว้ในหลายหน้า