Capítulo 48 de 116
useActionState combines a reducer-style state update with a pending flag specifically for Actions (async functions triggered by form submission or a transition), so a form's pending/result state doesn't need to be hand-wired with separate useState calls.
const [state, dispatchAction, isPending] = useActionState(reducerAction, initialState, permalink?).reducerAction(previousState, actionPayload): called each time the returned dispatchAction fires; receives the previous state (or initialState on the very first call) plus whatever payload was dispatched, and returns the new state.state (current, starts as initialState), dispatchAction (call this from a form's action prop or an event handler to trigger the update — has a stable identity across renders), isPending (true while a dispatched Action is in flight).dispatchAction calls are queued and run in order, each reducerAction call receiving the previous call's result — never run concurrently against each other.permalink (optional): for React Server Components progressive enhancement — if the form is submitted before the JS bundle loads, the browser navigates to this URL instead of the current page, so the same component (with matching reducerAction/permalink) must render on the destination page too.function reducerAction(previousState, payload) {
return { ...previousState, count: previousState.count + payload.amount };
}
function Cart({ initialState }) {
const [state, dispatchAction, isPending] = useActionState(reducerAction, initialState);
return (
<form action={() => dispatchAction({ amount: 1 })}>
<button disabled={isPending}>Add ({state.count})</button>
</form>
);
}
action directly to dispatchAction, with isPending disabling the button while the Action is in flight — no separate useState for the pending flag.useReducer + manual isPending state whenever the state update is driven by a form Action or transition-triggered function.dispatchAction's stable identity means it's safe to omit from Effect dependency arrays without causing stale closures.permalink only matters for RSC progressive-enhancement forms — most client-only forms can ignore it entirely.