Extra Arguments for Server Actions in React Forms

 by Robin Wieruch
 - Edit this Post

In this short tutorial, you will learn how to pass extra arguments to server actions in React forms. We will start with the following React form component that updates a user's profile:

type ProfileFormProps = {
user: {
id: string;
name: string;
};
};
const ProfileForm = ({ user }: ProfileFormProps) => {
const updateProfile = (formData: FormData) => {
const data = {
username: formData.get("username"),
};
console.log(data);
// TODO: do call (e.g. API call) to update the profile
};
return (
<form action={updateProfile}>
<label htmlFor="username">Username:</label>
<input name="username" id="username" />
<button type="submit">Send</button>
</form>
);
};

In the above code snippet, the updateProfile function is called when the form is submitted. The form action receives the raw form data as an argument and can extra the data from it. But what if you want to pass extra arguments to the updateProfile function? For example, you want to pass the user's id along with the form data. How can you achieve this?

const App = () => {
return (
<ProfileForm
// hardcoding the user object for demonstration
user={{
id: "1",
name: "Alice",
}}
/>
);
};

In a client-side form action, you could just take the id from the outer scope and pass it to the updateProfile function before this function hits the server.

const ProfileForm = ({ user }: ProfileFormProps) => {
const updateProfile = (formData: FormData) => {
const data = {
username: formData.get("username"),
};
console.log(data);
console.log(user.id);
};
return ( ... );
};

But in a server-side form action (read: server action), you can't access the user object from the outer scope. Instead, we will learn about two ways to pass extra arguments to server actions in React forms.

Hidden Form Fields for Extra Arguments

One way to pass extra arguments to server actions in React forms is by using hidden form fields. You can add hidden input fields to the form and set their values to the extra arguments you want to pass.

const ProfileForm = ({ user }: ProfileFormProps) => {
const updateProfile = async (formData: FormData) => {
"use server";
const data = {
id: formData.get("id"),
username: formData.get("username"),
};
console.log(data);
};
return (
<form action={updateProfile}>
<input type="hidden" name="id" value={user.id} />
<label htmlFor="username">Username:</label>
<input name="username" id="username" />
<button type="submit">Send</button>
</form>
);
};

In the above code snippet, we added a hidden input field with the name id and the value of user.id. When the form action is submitted, the updateProfile function receives the id in the form data.

Binding Extra Arguments to Server Actions

Another way to pass extra arguments to server actions in React forms is by binding the extra arguments to the server action. You can use the Function.prototype.bind() method to bind the extra arguments to the server action.

const ProfileForm = ({ user }: ProfileFormProps) => {
const updateProfile = async (id: string, formData: FormData) => {
"use server";
const data = {
id,
username: formData.get("username"),
};
console.log(data);
};
return (
<form action={updateProfile.bind(null, user.id)}>
<label htmlFor="username">Username:</label>
<input name="username" id="username" />
<button type="submit">Send</button>
</form>
);
};

In the above code snippet, we used the updateProfile.bind(null, user.id) to bind the user.id to the updateProfile function. When the form action is submitted, the server action receives the id as the first argument and the form data as the second argument.


Now you know how to pass extra arguments to server actions in React forms. You can use hidden form fields or bind the extra arguments to the server action. Choose the method that best fits your use case and requirements.

Currently I am working on a new course called "The Road to Next" which will hopefully match the popularity of The Road to React. We will create a full-stack Next application which goes all the way from fundamental React knowledge to accessing a serverless database. I am more than excited to share all my knowledge about Next.js with you. If you are interested, check out the website and join the waitlist.

Keep reading about 

GraphQL resolvers are used to resolve GraphQL queries to actual data. In this GraphQL tutorial, you will learn how to set up a GraphQL middleware for these resolvers for dealing with authorization and…

In this short tutorial, you will learn about multiple ways to show a loading spinner in React forms when using actions with a pending state. You can use the loading state to indicate that the form is…

The Road to React

Learn React by building real world applications. No setup configuration. No tooling. Plain React in 200+ pages of learning material. Learn React like 50.000+ readers.

Get it on Amazon.