Server Actions for Powerful Forms

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional NextJS Lessons

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
🚨 Work In Progress 🚧
Subscribe for Launch

Server Actions for Powerful Forms

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Core Concept

Modern React extends the action prop of the native html form’s allowing you to easily invoke server functions without having to explicitly create HTTP Apis.

Server Functions invoked from a form.action prop are called Server Actions.

Native form action

Native browser form elements provide an action prop where you can pass in a URL which will be invoked with FormData upon form submission.

We could actually create a custom HTTP API with nextjs to handle the native "action -> HTTP API URL" functionality as shown below.

app/page.tsx
app/api/login/route.ts
"use client";

import { useState } from "react";

export default function Page() {
const [name, setName] = useState("");
return (
<div className="root">
<form action="/api/login" method="POST">
<input
name="username"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
<button type="submit">Submit</button>
</form>
</div>
);
}

Extension to invoke Server Functions

Instead of passing in a url to the action prop, with modern React you can even directly pass in a server function which will automatically be invoked upon form submission with the FormData passed in as the argument.

This is demonstrated in the below example where our server function is directly invoked from the action prop with the FormData containing the fields in the form (username).

app/page.tsx
lib/functions.ts
"use client";

import { login } from "@/lib/functions";
import { useState } from "react";

export default function Page() {
const [name, setName] = useState("");

return (
<div className="root">
<form action={login}>
<input
name="username"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
<button type="submit">Submit</button>
</form>
</div>
);
}

Create a Wrapper

Note that instead of passing in the server function directly to the action prop you can create a wrapper (e.g. with useTransition) which allows you provide better handling of the inputs and the outputs of the server function.

This is demonstrated in the below example where we invoke the server function with an object that has a well defined structure and then process the response to display it to the user.

app/page.tsx
lib/functions.ts
"use client";

import { useState, useTransition } from "react";
import { login, LoginResponse } from "@/lib/functions";

export default function Page() {
const [name, setName] = useState("");
const [isPending, startTransition] = useTransition();
const [serverResult, setServerResult] = useState<LoginResponse | null>(null);

function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setName(e.target.value);
setServerResult(null);
}

function handleSubmit() {
startTransition(async () => {
const result = await login({ username: name });
setServerResult(result);
});
}

return (
<div className="root">
<form action={handleSubmit}>
<input
name="username"
value={name}
onChange={handleChange}
placeholder="Enter your username"
disabled={isPending}
/>
<button type="submit" disabled={isPending}>
Submit
</button>
</form>

{serverResult != null && (
<p className={serverResult.type}>{serverResult.message}</p>
)}
</div>
);
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

Modern React extens the action prop of the native HTML form allowing you to easily invoke server functions without having to explicitly create HTT P APIs. Server functions passed as an action prop are called server actions. Let's do a quick recap of how HTML forms work in the browser without using the extensions offered by React. To demonstrate the native functionality of form elements, we create a new API route under slash API slash login. This API will eventually be invoked automatically by the native functionality offered

00:32

by the browser form element. We export a post s TT P method and we expect the request to have what is called form data. The next request API makes it quite easy to access this form data and then slice and dice it. For example, from this form data, we can read a field as an example. We expect there to be a username field. Now that we've passed this field from the incoming request, we can use it however we want. For example, we are going to simply return it as a part of the response payload to demonstrate how a form element interacts with an API provided as an action prop, we are going to create a very simple page.

01:04

We create a state so that we can accept a value from the user and then we create a form element and note that the action prop is pointing to that API we just created, which is slash api slash login. Along with the method post, this form is going to contain an input field and the name prop over here is actually quite important. The HTML form automatically collects the fields with the various names and bundles it into a form data that it'll eventually pass to the action URL. We also give the user a nice button so that they can submit the form. With this user interface, we expect the backend API to be invoked with the form data

01:38

that contains the username field as provided by the user. So let's see it in action. Within the browser, we provide a username and then click that submit button and no surprise our API is triggered and that passes the form data body to return back to US adjacent play road displaying the input username instead of passing in a URL to the action prop. With modern react, you can even directly pass in a server function, which will automatically be invoked upon form submission. With the form data are passed in as the argument, so we create a new server function by starting in the context of use server. And this function is going to directly accept the form data.

02:13

We no longer need to accept a request and passe it out. And with this form data we can read any field as we did before. Here we are reading the field username and we are simply going to log it to the console. As we know within our client page, we can directly import our server function and then for our form, instead of passing in a URL in a method, we can directly pass this server function into the action prop. Now let's demonstrate that submitting a form indeed invokes this server function with the correct form data. By opening this up within the browser. When we run the application, we are presented

02:46

with the same user interfaces before, but this time when we submit the form, we can see on the server logs that the form data was directly passed into our server function, which logged the username field to the console. Note that Instead of passing in the server function directly to the action prop, you can create a rapport which allows you to provide better handling of the inputs and the outputs of the server function. We are going to create a new server function for this demonstration, which is going to return a well-structured response with the Thai field, which might be success or error. Along with the message that we want to display to the user. The input of a server function is going

03:20

to be well structured as well. It is simply going to be an object containing a username of type string, and then we will eventually return a promise to the login response. Within the body of this login function, we simply check if a username is not provided and if that is the case, we return an object with type error along with a message to display to the user. Otherwise, we simply return an object with type success and a message that echoes back that username. To effectively demonstrate using this function from a client, we will create a new custom client page. We start by bringing in the login function along with the login response type.

03:52

Within the page, we set up a state variable, which will help us collect the name from the user. And as we've previously seen in our lesson dedicated to server functions, we will track when a server action is pending with use transition. Finally, in order to display the result of our server action back to the user, we create another state variable typed as login response, or now which we initialize to null is we don't have a server response yet. We create a simple handler to handle the change on the input, which will modify the name state with the user provided value and clear any server state that we might have collected before.

04:24

Then we have a second handler for the form submission instead of invoking login directly. We do that within the context of a start transition. We simply invoke it with the correct payload and then store the result in our server result state. For our user interface, we render out a simple form with the action wide to this handle, submit function and input with the value and on change wide to our state using the disabled prop. We will also disable this input if a server action is pending. Next to the input, we have a submit button that is also disabled on a pending server action. And finally, if we have a server result,

04:57

we will display the message under the form with this user interface created. Let's demonstrate it within the browser. If you try to submit the form without a username, the server will return a type error along with the message and we display that message to the user. If you modify that value, the server result is cleared and when we submit it again this time with a valid username, we get back a success message that echoes the username back to us. To recap, we are simply creating a wrapper around a server function using start transition, which is something that we have also done previously in our lesson on server functions,

05:30

and then wiring this containing function to the form action.

Professional NextJS

Professional NextJS

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
🚨 Work In Progress 🚧
Subscribe for Launch