Creating a Server Action for Form Data
So far, we've explored two out of four different types of interaction with the server: an API endpoint that takes JSON and another that takes form data.
Now we'll dive into creating a server action and using it to submit data.
Creating a Server Action
Server actions can be placed within a Re
Transcript
00:00 All right, so far we've taken a look at two of our four different types of interactions with the server. We've looked at an API endpoint that takes JSON and another that takes form data. Now let's try and create a server action and use a server action to submit the data. Now you can either put a server action in a React server component, like page, or you can create a different file. I'll show you that in a bit.
00:20 But I'm just going to go and create the server action in page.tsx. Now I'm going to call this server action onDataAction. It's going to be an async function. And we'll just pass it on to our ClientComponent. Now our ClientComponent isn't expecting that property, so maybe that's what it's telling us.
00:35 Let's give it a try and see what happens on the client. All right, so we get a runtime error about how a event handler, in this case, cannot be passed to a ClientComponent prop from an RSC. Why does it think it's an event handler? Well, it thinks it's an event handler because it doesn't know it is a server action.
00:53 Now to do that, we're going to add useServer. That tells Next.js that this is a server-only function. Let's go take a look. And now it's happy. TypeScript isn't so happy, though, because onDataAction isn't defined as a property onRegistrationForm.
01:13 So let's go and add that. All right, so we'll define that as a function. It takes data. Currently, we'll just define that as any. And it returns a promise, since it's an async function, to avoid. So it doesn't return anything. And now let's just use it.
01:27 So instead of either fetch here, we're going to just invoke it. We'll hit Save. We'll hit Submit.
01:44 And now nothing seems to happen, but if I look on the terminal, ah, there we go. There's our data all the way back on the server. Awesome. Well, let's start getting the typing right. So on this side, it's pretty much as easy as just doing the infer for data. And it's the same thing on the other side.
02:04 So let's bring in Zod and the schema. And then again, we'll infer. And there we go. Now we got our typing. But of course, we always want to check that data.
02:22 So let's go and add in our save parse. So now we're going to save parse our schema. And then if we parse successfully, we've got the actual data. Then we are going to do similar things to what we did before. We're going to return a message that has the user. And if we are invalid, then we return a message of invalid data.
02:40 And we give back a list of all of the issues. Now if we look down here, we can see that TypeScript is not happy again. And that's because the output of this function is no longer a void. It's a object that has either a message and user or a message and issues. So back in our registration form, let's go and change the promise here to match that schema.
03:00 So a message, which is a string. If it's a user, it's going to have the type of that schema. Otherwise, it's going to have a list of issues. And let's go down here and console log out the output. Of course, we have to await it. Let's give it a go.
03:20 And there we go. Our user is registered all the way out to the server and back, just using a server action. For our fourth method, we are going to use form data again. So we're going to take that exact same code and then rewrite it
03:39 to use form data instead. I leave that to you in the instructions. I'll check in the next video, and you can see how I did it.