<Form action={myServerAction}>
(or <form>
with formAction={…}
) and the action
prop is a Server Action, Next.js intercepts the native form submission.fetch
call to invoke your server function, then re-renders the current route via client-side navigation.<aside>
What actually happens after the fetch
call is router.refresh()
(automatic in App Router).
This re-executes the Server Components for the current route segment and streams the new HTML, but it is not a real browser navigation or a “hard reload.” It feels like a full re-render because every Server Component in that segment mounts again, but the client-side JS state outside the refreshed subtree survives. </aside>
This full-page re-render resets all uncontrolled inputs to their initial values (i.e. “clears” the form).
value
via useState
.form.reset()
in React 19form.reset()
after a successful Server Action (or when using useActionState
), mimicking full-page navigation.selectedIndex
, checked
) to their default values before React’s next commit, causing a mismatch.<aside>
form.reset()
only when the <form>
specifies an action
attribute (string URL or function reference / server action) or when you use useActionState
/ useFormState
.<form onSubmit={…}>
without an action
attribute does not get auto-reset.
</aside>reset()
mutates the DOM directly. React hasn’t yet reconciled, so if it believes a controlled prop hasn’t changed, it won’t overwrite the reset DOM.value
on every commit, so even if reset()
clears them, React immediately restores your controlled value
.<select>
/ <input type="checkbox">
: Due to Bug #30580, controlled props are only re-written on mount or when the prop itself changes. An external reset()
isn’t regarded as a prop change, so their values stay cleared.<aside>
Note that the team marked it “accepted” and it should be fixed before React 19 final—but today (React 19 RC) it still happens.
</aside>