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

Actions & useActionState

ก่อนมี Actions การ submit form หมายถึงต้อง wire state สามชิ้นด้วยมือ และต้องจำอัปเดตทุกตัว:

// The old way — lots of manual bookkeeping.
function ChangeName() {
const [name, setName] = useState('');
const [isPending, setIsPending] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(e) {
e.preventDefault();
setIsPending(true);
setError(null);
try {
await updateName(name);
} catch (err) {
setError(err.message);
} finally {
setIsPending(false); // must not forget this
}
}
// ...form wired to handleSubmit
}

async form ทุกอันในแอปทำซ้ำแบบนี้: loading flag, error slot, try/catch/finally ทั้งหมดนี้คือ boilerplate และถ้าลืม finally spinner จะค้างตลอดกาล

Action ก็แค่ async function ที่คุณส่งให้ <form> ผ่าน prop action React เรียก function นี้ตอน submit, ส่ง FormData ให้ และจัดการ pending state กับการ reset form ให้:

<form action={async (formData) => {
await updateName(formData.get('name'));
}}>
<input name="name" />
<button type="submit">Update</button>
</form>

ไม่ต้อง onSubmit, ไม่ต้อง preventDefault, ไม่ต้องประกอบ FormData เอง แต่คุณยังต้องการ state ของ pending และ error เพื่อแสดงให้ user เห็นว่าเกิดอะไรขึ้น — นั่นคือสิ่งที่ useActionState เพิ่มเข้ามา

useActionState(action, initialState) ห่อ action ของคุณและคืน tuple สามตัว: state ปัจจุบัน, action ที่ห่อแล้วสำหรับส่งให้ form และ boolean pending

import { useActionState } from 'react';
function ChangeName() {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await updateName(formData.get('name'));
if (error) {
return error; // returned value becomes the new state
}
redirect('/profile');
return null; // success: clear the error
},
null, // initial state
);
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Update</button>
{error && <p>{error}</p>}
</form>
);
}

อ่าน shape ให้ดี ๆ — นี่คือส่วนที่คนมักทำผิด:

  • action รับ (previousState, formData) และ return state ถัดไป
  • useActionState คืน [state, formAction, isPending]state คือค่าที่ action คุณ return ล่าสุด, formAction คือสิ่งที่ส่งให้ <form action={...}> และ isPending ถูกจัดการให้
sequenceDiagram
  participant U as User
  participant F as form action
  participant A as your async action
  U->>F: submit
  F->>F: isPending = true
  F->>A: action(prevState, formData)
  A-->>F: returns next state
  F->>F: isPending = false, state updated
  F->>U: re-render with new state
lifecycle ของ Action

ทั้งการเต้นสามจังหวะ — loading flag, error slot, try/catch/finally — ยุบเหลือ hook เดียวที่ลืม reset spinner ไม่ได้

"Action" ของ React 19 คืออะไร?
`useActionState(action, initialState)` คืนอะไร?
action ที่ส่งให้ useActionState รับ argument อะไร?
useActionState แทนที่ boilerplate อะไร?