Modern Web · React

React 19 Form Actions — A Field Guide

React 19 lets a form's action prop take a function directly, resets the form automatically on success, and gives child inputs pending state through useFormStatus without prop drilling.

John Kihiu12 min read

The detail that surprised me most about React 19's form handling is how little code it takes away — a form that posts data, resets itself, and shows a child button's pending state used to mean three separate pieces of local state wired together by hand. Now the form element itself carries that behavior, and a component nested three levels deep can read the pending flag without a single prop passed down to it.

The action prop on <form>

React 19's DOM bindings let <form> accept a function directly on its action attribute, not just a URL string. Pass it a function and React intercepts the submit, calls the function with the form's FormData, and — this is the part that used to require a manual reset() call — resets the form's uncontrolled inputs automatically once the action resolves successfully. If the action throws or the returned state signals failure, the form is left as-is so the user doesn't lose what they typed.

TSX · form action prop
async function addComment(prevState: { error?: string }, formData: FormData) {
  const text = String(formData.get('comment') || '').trim();
  if (!text) return { error: 'Comment cannot be empty' };

  const res = await fetch('/api/comments', {
    method: 'POST',
    body: JSON.stringify({ text }),
  });
  if (!res.ok) return { error: 'Failed to post comment' };

  return {}; // no error → React clears the uncontrolled inputs
}

export function CommentForm() {
  const [state, formAction] = useActionState(addComment, {});

  return (