How to create forms with Server Actions
React Server Actions are Server Functions that execute on the server. They can be called in Server and Client Components to handle form submissions. This guide will walk you through how to create forms in Next.js with Server Actions.
How it works
React extends the HTML <form>
element to allow Server Actions to be invoked with the action
attribute.
When used in a form, the function automatically receives the FormData
object. You can then extract the data using the native FormData
methods:
Good to know: When working with forms that have multiple fields, you can use the
entries()
method with JavaScript'sObject.fromEntries()
. For example:const rawFormData = Object.fromEntries(formData)
.
Passing additional arguments
Outside of form fields, you can pass additional arguments to a Server Function using the JavaScript bind
method. For example, to pass the userId
argument to the updateUser
Server Function:
The Server Function will receive the userId
as an additional argument:
Good to know:
- An alternative is to pass arguments as hidden input fields in the form (e.g.
<input type="hidden" name="userId" value={userId} />
). However, the value will be part of the rendered HTML and will not be encoded.bind
works in both Server and Client Components and supports progressive enhancement.
Form validation
Forms can be validate on the client or server.
- For client-side validation, you can use the HTML attributes like
required
andtype="email"
for basic validation. - For server-side validation, you can use a library like zod to validate the form fields. For example:
Validation errors
To display validation errors or messages, turn the component that defines the <form>
into a Client Component and use React useActionState
.
When using useActionState
, the Server function signature will change to receive a new prevState
or initialState
parameter as its first argument.
You can then conditionally render the error message based on the state
object.
Pending states
The useActionState
hook exposes a pending
boolean that can be used to show a loading indicator or disable the submit button while the action is being executed.
Alternatively, you can use the useFormStatus
hook to show a loading indicator while the action is being executed. When using this hook, you'll need to create a separate component to render the loading indicator. For example, to disable the button when the action is pending:
You can then nest the SubmitButton
component inside the form:
Good to know: In React 19,
useFormStatus
includes additional keys on the returned object, like data, method, and action. If you are not using React 19, only thepending
key is available.
Optimistic updates
You can use the React useOptimistic
hook to optimistically update the UI before the Server Function finishes executing, rather than waiting for the response:
Nested form elements
You can call Server Actions in elements nested inside <form>
such as <button>
, <input type="submit">
, and <input type="image">
. These elements accept the formAction
prop or event handlers.
This is useful in cases where you want to call multiple Server Actions within a form. For example, you can create a specific <button>
element for saving a post draft in addition to publishing it. See the React <form>
docs for more information.
Programmatic form submission
You can trigger a form submission programmatically using the requestSubmit()
method. For example, when the user submits a form using the ⌘
+ Enter
keyboard shortcut, you can listen for the onKeyDown
event:
This will trigger the submission of the nearest <form>
ancestor, which will invoke the Server Function.