<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ server actions - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ server actions - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 26 Jul 2026 11:16:59 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/server-actions/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Pass Additional Arguments to Next.js Server Actions ]]>
                </title>
                <description>
                    <![CDATA[ Asynchronous data mutation and handling is a necessary task in modern web applications. You may want to execute a standalone asynchronous function on the server to carryout tasks like saving data to the data store, sending emails, downloading PDFs, p... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-pass-additional-arguments-to-nextjs-server-actions/</link>
                <guid isPermaLink="false">6717fde839354c63841ba816</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Tue, 22 Oct 2024 19:32:56 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729165969570/14ca2ef4-8a08-40f8-ba70-c6c24c194850.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Asynchronous data mutation and handling is a necessary task in modern web applications. You may want to execute a standalone asynchronous function on the server to carryout tasks like saving data to the data store, sending emails, downloading PDFs, processing images, and so on.</p>
<p>Next.js provides us with <code>Server Actions</code> which are asynchronous functions that execute on the server. We can use server actions for data mutations on the server, but server actions can be invoked from both server and client components.</p>
<p>Server actions are a great way to handle form submissions by executing the action when the form data gets submitted. In this article, we will look into a practical use case of handling additional arguments in Next.js server actions.</p>
<p>If you are interested in learning Next.js Server Actions with design patterns and project building, I have created a crash course for you that you can find <a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">here</a>.</p>
<p>Also, this article is also available as a video tutorial here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9PBtj0sUc7Q" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-would-you-need-to-pass-additional-arguments">Why Would You Need to Pass Additional Arguments?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-form-with-a-server-action">A Form with a Server Action</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-pass-additional-arguments">How to Pass Additional Arguments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-about-the-hidden-fields">What About the Hidden Fields?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resources">Resources</a></p>
</li>
</ol>
<h2 id="heading-why-would-you-need-to-pass-additional-arguments">Why Would You Need to Pass Additional Arguments?</h2>
<p>When we execute a server action on a form submission, the server action gets the form data automatically. For example, take a look at the form below:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updateUser}</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Here, we are executing a server action called <code>updateUser</code> when the form gets submitted. The <code>updateUser</code> function will receive the submitted form data as an argument which can be used to extract the form field values.</p>
<p>As you see in the code snippet below, the <code>updateUser</code> function gets a <code>formData</code> as an argument, and we can extract the value of the <code>name</code> field from it.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(name);
}
</code></pre>
<p>While this pattern covers most of the basic use cases, you may need to pass additional arguments programmatically to the server actions. These arguments are not part of the form or form data or user input data. They may be programmatically passed values to your server action.</p>
<p>To understand this, check the server action code snippet below. It’s the same server action we have seen before, but we have passed an additional <code>userId</code> argument along with the regular <code>formData</code> argument.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">userId, formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(userId);
  <span class="hljs-built_in">console</span>.log(name);
}
</code></pre>
<p>The <code>userId</code> value is something internal to the application – and you wouldn’t ask a user to submit the value as part of the form submission. Rather, you may need to pass it programmatically to your server action to perform further computations.</p>
<p>Right, that’s the use case we’re talking about. As we understand why we need it, let’s understand how to achieve it. But first, let’s create a form and a working server action for it.</p>
<h2 id="heading-a-form-with-a-server-action">A Form With a Server Action</h2>
<p>Create a directory called <code>actions</code> under the <code>app</code> directory of your Next.js application. Now create a <code>user.js</code> file under the <code>actions</code> folder with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(name);

  <span class="hljs-comment">// Do anything with the name, save in DB, create invoice, whatever!</span>
}
</code></pre>
<p>This is how you create a server function in Next.js. It must have a <code>”use server”</code> directive at the top of the file to tell Next.js that this is a special file with one or more asynchronous functions to execute on the server.</p>
<p>Then we have the server action (the async function) <code>updateUser</code> with <code>formData</code> as the argument. Inside the function definition, we extract out the <code>name</code> value and print it on the console.</p>
<p>Let’s now attach this server action to a form. To do that, create a folder called <code>components</code> under the project root folder. Create a file called <code>user-form.jsx</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Input } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/input"</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/button"</span>

<span class="hljs-keyword">import</span> { updateUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/app/actions/user"</span>

<span class="hljs-keyword">const</span> UserForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span>(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updateUser}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UserForm;
</code></pre>
<p>This is a simple React component with a form. The form has one input text field called <code>name</code> and a submit button to submit the form. The form has an <code>action</code> attribute with the server action <code>updateUser</code> as the value. Now, when the form gets submitted with a <code>name</code> value, the server action will get it as part of the form data as we discussed above.</p>
<p>Let’s test it out. To do that, we’ll create a Next.js route and page where we can use the <code>UserForm</code> component. Create a folder called <code>extra-args</code> under the <code>app</code> directory. Now, create a file called <code>page.js</code> under the <code>app/extra-args</code> directory with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> UserForm <span class="hljs-keyword">from</span> <span class="hljs-string">"@/components/user-form"</span>;

<span class="hljs-keyword">const</span> ExtraArgsDemo = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserForm</span> /&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExtraArgsDemo;
</code></pre>
<p>This is a simple React component where we have imported the <code>UserForm</code> component and used it in the JSX. Now run the local server and access this route <code>localhost:3000/extra-args</code>. You should see the form with a text field and a button.</p>
<p>Type some text inside the text field and click on the button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167845597/b4c58399-4188-4b89-8ec7-dd2602c10ccd.png" alt="Application with server actions" class="image--center mx-auto" width="1534" height="824" loading="lazy"></p>
<p>Now, you will be able to see that the typed text has been printed on the server console. Why on the server console? Why not on the browser console? This is because server actions execute on the server, not on the client side browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167722231/e8c40a4d-e506-42fb-8ea3-233e295ac534.png" alt="Output Mike" class="image--center mx-auto" width="900" height="408" loading="lazy"></p>
<p>So, with this we have now established a data flow like this:</p>
<p>Page =&gt; Form =&gt; Server Action</p>
<p>The page has a form. The form execute a server action on submission. The server action prints a form data on the server console.</p>
<p>Let’s now enhance these pieces to pass additional arguments to the server action.</p>
<h2 id="heading-how-to-pass-additional-arguments">How to Pass Additional Arguments</h2>
<p>Let’s pass a prop to the <code>UserForm</code> component from the page. We’ll pass a <code>userId</code> with a value to pretend that we are passing this userId programmatically to our form and to the server action from there.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> UserForm <span class="hljs-keyword">from</span> <span class="hljs-string">"@/components/user-form"</span>;

<span class="hljs-keyword">const</span> ExtraArgsDemo = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserForm</span> <span class="hljs-attr">userId</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">1234</span>"} /&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExtraArgsDemo;
</code></pre>
<p>In the <code>UserForm</code> component, we accept the <code>userId</code> prop. Now, we have to do something special to pass this userId to the <code>updateUser</code> server action.</p>
<p>JavaScript has a magical method called <code>bind()</code> that helps us create a <code>Partially Applied Function</code>. With this <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#partially_applied_functions">partially applied function</a>, you can create a function from another function’s preset arguments.</p>
<p>In our case, the <code>updateUser</code> function already has an argument called <code>formData</code>. Now we can pass <code>userId</code> as the additional argument using the <code>bind()</code> method to create a new function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> updatedUserWithId = updateUser.bind(<span class="hljs-literal">null</span>, userId);
</code></pre>
<p>The first argument of the <code>bind()</code> method is the context you are binding the function to. The context handles the association of the function with the <code>this</code> keyword value. In our case, we can keep it <code>null</code> as we are not changing it. After that, we passed the new argument <code>userId</code>. It’s good to know that the <code>bind()</code> method works on both server and client components.</p>
<p>Here is the modified <code>UserForm</code> component (<code>user-form.jsx</code> file). Note that the form action value is now modified to the new function <code>updatedUserWithId</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Input } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/input"</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/button"</span>

<span class="hljs-keyword">import</span> { updateUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/app/actions/user"</span>

<span class="hljs-keyword">const</span> UserForm = <span class="hljs-function">(<span class="hljs-params">{userId}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> updatedUserWithId = updateUser.bind(<span class="hljs-literal">null</span>, userId);

  <span class="hljs-keyword">return</span>(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updatedUserWithId}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UserForm;
</code></pre>
<p>Now, the server action will receive the <code>userId</code> value as an argument. Let’s print that to the console as well.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">userId, formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(userId);
  <span class="hljs-built_in">console</span>.log(name);

  <span class="hljs-comment">// Do anything with the user id and name, save in DB, </span>
  <span class="hljs-comment">// create invoice, whatever!</span>
}
</code></pre>
<p>Now if you submit the form with a name value:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167845597/b4c58399-4188-4b89-8ec7-dd2602c10ccd.png" alt="Application with server actions again" class="image--center mx-auto" width="1534" height="824" loading="lazy"></p>
<p>You’ll see that both userId and the name values are logged into the server console. Great! We have logged one value from the form data, and the other one was passed internally to the server action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729169164296/d0ef49f8-88bc-4e82-a509-cbb859df87e1.png" alt="d0ef49f8-88bc-4e82-a509-cbb859df87e1" class="image--center mx-auto" width="830" height="312" loading="lazy"></p>
<p>So, we learned how to pass the extra arguments to the server action along with the form data.</p>
<h2 id="heading-what-about-the-hidden-fields">What About the Hidden Fields?</h2>
<p>HTML supports a hidden type form field to pass client data to the server without accepting the input from the users. So this means that we could have used the hidden field to pass the <code>userId</code> value like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729485711865/21f33410-fcdd-46ea-b14c-d57004b30a96.png" alt="hidden field" class="image--center mx-auto" width="744" height="151" loading="lazy"></p>
<p>So why did we do all that with the <code>bind()</code> method? Well, because of security concerns. When you pass data using hidden fields, the value will be part of the rendered HTML, and it will not be encoded as well. So it’s better to handle it programmatically.</p>
<h2 id="heading-resources">Resources</h2>
<p>That's all for now. Did you enjoy reading this article and have you learned something new? If so, I would love to know if the content was helpful. Let me share a few additional resources you may need:</p>
<ul>
<li><p>All the Source Code used in this article is <a target="_blank" href="https://github.com/atapas/nextjs-email/tree/extra-arg">on my GitHub</a>.</p>
</li>
<li><p>Here’s the <a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">Server Action Crash Course with Patterns and Project</a>.</p>
</li>
<li><p>Here’s the <a target="_blank" href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations">Server Action Official Documentation</a> if you want to read more.</p>
</li>
<li><p>And you can read more about the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind() method here</a>.</p>
</li>
</ul>
<p>Additionally, you can connect with me by:</p>
<ul>
<li><p>Subscribing to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>. If you are willing to learn <code>React</code> and its ecosystem, like <code>Next.js</code>, with both fundamental concepts and projects, I have great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 25+ video tutorials and 15+ hours of engaging content so far, for free. I hope you like them as well.</p>
</li>
<li><p><a target="_blank" href="https://twitter.com/tapasadhikary">Following me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Checking out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
<li><p>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
