Gorkem Arpaci
Server Actions are often used especially with forms. Using the HTML form element is the conventional method for mutating data. Let's dive into using Server Actions with forms and reset the form fields after submission.
Before continue, let's explain the convention when using Server Actions. It's important to understand the difference between using them with Server Components and Client Components.
Here, the action is specified outside the component and then imported. To enable this functionality, we utilize the "use server" directive at the beginning of the file.
actions.js
'use server';
export async function submit() {
// ...
}form.js
'use client';
import { submit } from './actions';
export function Form() {
return <form action={submit}>{/* ... */}</form>;
}In Server Components, the action can be embedded directly and utilized alongside the "use server" directive, which should be positioned at the beginning of the action body.
form.js
export function Form() {
async function submit() {
'use server';
// ...
}
return <form action={submit}>{/* ... */}</form>;
}Another approach is to define the action externally to the component and then import it. In such cases, the "use server" directive is not required within the function body but should be placed at the top of the action file instead, like we did in client components when we are importing the server action.
actions.js
'use server';
export async function submit() {
// ...
}form.js
import { submit } from './actions';
export function Form() {
return <form action={submit}>{/* ... */}</form>;
}Let's create a basic form that demonstrates Server Actions to dispatch the data to the server. For this illustration, we will simply return the submitted data within the action. In practical applications, you might intend to modify the data server-side, such as creating or updating (CRUD operations) a database record. Our form will comprise only one input field for the username and a submit button. As it's a Server Component, the action is embedded inline and incorporates the "use server" directive.
form.js
export function Form() {
async function submit(formData: FormData) {
'use server';
const username = formData.get('username');
return username;
}
return (
<form action={submit}>
<input name="username" />
<button type="submit">Submit</button>
</form>
);
}Upon form submission, our aim is to reset the form fields. This can be accomplished by utilizing the reset method on the form element. To access the form element, we will employ the useRef hook and assign it to the form element. This will yield the form object containing the reset method, which we can invoke within the action. Since hooks are exclusive to Client Components, we will need to mark our component as a Client Component by employing the "use client" directive. Additionally, we must move our action to a distinct file and import it accordingly.
actions.js
'use server';
export async function submit(formData: FormData) {
const username = formData.get('username');
const email = formData.get('email');
return username + email;
}form.js
'use client';
import { submit } from '@/app/actions';
import { useRef } from 'react';
export function Form() {
const ref = useRef<HTMLFormElement>(null);
return (
<form
ref={ref}
action={async (formData) => {
const res = await submit(formData);
if (res) ref.current?.reset();
}}
>
<input name="username" />
<input name="email" />
<button type="submit">Submit</button>
</form>
);
}
This approach offers the benefits of both worlds: employing Server Actions within Client Components to reset the form. We can apply this same pattern to manage other form-related functions, such as displaying a loading indicator or disabling the submit button during action execution. Likewise, we can refresh data using revalidateTag or revalidatePath, or redirect to an alternative route.
Congratz! We made a quick intro how to use Server actions with HTML form elements with Client and Server components. Additionally, inline and imported ways of usage of server actions were also covered. The powerful useRef hook come to rescue the day when it comes to resetting the form fields after submission thus we do not need to keep track of form fields some state values in order to clear them.
Thank you for reading this far. See you in the next chapter :)