Current section: Server Actions 27 exercises
solution

Action Reference

Loading solution

Transcript

00:00 The first thing let's do is go to the code for our editable text. So edit text right here, and we want to be able to accept an action prop for this component, so that we can use this all over the place. It accepts an action prop. So whatever thing you want to have happen when we submit this form,

00:19 give me an action and I'll call that. So we'll add action right here, and then we're going to stick that inside of a use action state. So this is going to give us our form state, form action, and is pending. Form state, form action, and is pending. This is going to come from use action state,

00:39 which is going to come from React. So that import isn't working for me. Let's just pull that in right here. Great. That then gives us some stuff. So our form action can go as the action prop here. Action is our form action.

00:58 Usubmit, we want to keep around because we want to manage the setting the value, flushing sync, and focusing the button and everything. Pretty often, you're not actually going to keep the Usubmit around. Often, you'll get rid of Usubmit and just use the action, but we have specific things we want to do with our on-submit handler. So we can at least get rid of

01:17 prevent default because React is going to do that for us, which is cool. So we'll get rid of that, and we no longer care about the event. Cool. And then down here as extra credit, we can also display an error message that our users will be able to see like what error came back from the server

01:37 when if there was an error of any kind. So we'll stick this right here. If we've got form state, then we'll call h with div, and we have these props. Yep. Thank you. And we can pass in our form state message.

01:56 Now, of course, we've got some issues here. Otherwise, no, there we go. Dun, dun, dun, dun. And thank our lucky stars for prettier since we don't ever want to have to ever, ever, ever type that stuff ourselves. So form state will exist from our form action

02:13 when it's been submitted and when the response comes back. And so here, we want the form state status to return an error, and if it does, then it'll have read, and we want it to have a message also. So how do we make that happen? Well, let's come over to...

02:33 Oh, and of course, we also have our is pending state. We need to use that for showing some sort of pending UI during the process of submitting the form, which we're going to do right here. So if we've got some style and is pending, if we are in a pending state, whoops, we want opacity.

02:52 If we're in a pending state to be 0.6, there we go. Okay, so while we're submitting, we give the user some sort of feedback. Hey, yeah, I know that you're submitting. Okay, so with all that information coming from use action state, we want our form state, we want the return value of our action

03:11 to include a status and a message. So let's go to our actions. And right here, we're going to return a status of success and a message of success. In the error case, we'll return a, yep, a sure status and an error message.

03:30 So if the error message exists, then use that. Otherwise, just stringify the error. Okay, and then I'm going to leave this here. We'll come back to this here in just a moment. Finally, we need to actually import this action. So we're going to go to the ship details, and this is where we're going to pull in our ship name and pass it to the edit text.

03:49 So we're going to import update ship name from actions. And we come down here and add that as the action prop to our editable text. Okay, super. We'll get to this here in a second. So with those changes, now we're going to refresh and we're going to get an error. And the reason we get an error

04:09 is because we don't have that use server. And so if we take a look at the error, it's going to be, oh, function can't be directly, or pass directly to client components unless you explicitly expose it by marking with use server, or maybe you wanted to call it, so whatever. In our case, yeah, we don't want to actually take this.

04:29 So first of all, this is a server module right here. And so it is allowed to import the action. That's not the problem. The problem is we're taking this update ship name and we're passing it as a prop to a client component that needs to be serialized. So all this stuff is going to get serialized. The action needs to be serializable.

04:47 And right now it's just a regular function, so it's not. So what we're going to do is first, I'm going to get our logs in place so we can save that. And we'll come over here to our logs right here. And you notice it is just locking out the update ship name

05:08 and it doesn't have any special properties to speak of. Now, if we come over here to our server, then our RSC loader, uncomment this so that we can see what does it, change it to, and then we'll go to our actions and say use server, use server directive there.

05:29 Now I need to restart the server because we need to register that properly. So, or perhaps it'll actually just work, but I'm going to restart the server just to be safe and come over here and boom. Now, because we have use server, we are still actually, what's interesting about this

05:47 is that our module still has all of the original code. It just also has this register server reference. So that kind of differs from the client component because in the client component case or use client, it replaced the entire module with just this stuff. But the thing you need to remember is

06:05 this is all happening on the server side anyway. And so it's actually not a problem for it to maintain all of the existing code that it had before. We just need to additionally tack on a couple of properties onto our module that includes the module identifier. So like, where is that module from

06:23 and what is the export that it represents? And so you can actually find that right here. So we've got our type of, this is a React server reference. Here's our ID, which includes the path to the module and a hash sign or pound sign with the name of the export.

06:40 And then also some bound information that is gonna be useful to React on when this is ultimately going to get called. We actually don't end up using this ourselves. Okay, it's the ID that's most important for us. So with all of that information now, if I refresh the page, it's not gonna blow up

07:00 because now it's being serialized properly in our RSE endpoint. So if we come over here, refresh the page, then we actually look for file colon slash slash and there it is on line number 12. We've got the ID is the path to the module with the hash sign and then update chip name.

07:19 And then it's bound as null, whatever that's supposed to mean, I honestly don't know. Now, some of you are like, hold on a second, Kent. I've thought with this edit text thing, we didn't want to send the entire file URL or whatever to the client because it was wasteful, whatever. And yes, that's true. This is again, one of those situations

07:39 where the modules that we're using, the React server DOM ESM, which is responsible for this transformation, they're not optimized. So it's the fact that it shows the full file path, probably not a security vulnerability, maybe a little bit, but it's not a huge issue, but it's certainly not what you would want to do

07:57 in production and the bundlers that you've got will do things differently here as well. In any case, this is useful to us because now it means that when we submit our form, we can take this URL or this identifier and resolve it to the actual function that needs to be called right here, which is pretty sweet.

08:17 So let's review really quick what we did here. We updated the update chip name so that it returned some value so that in our edit text, that form state can be referenced when that return value shows up again. We also have our use action state here

08:36 where we pass the action that we get from props. So this is our client component referencing something that is coming from the server. And that is happening inside of our ship details right here, which gets that update chip name from the actions and then passes that update chip name

08:54 as the action for this editable text. And so all of this is server component stuff and we logged out the properties. We added an ID property and a type and a couple other properties onto this function. And all of that is already working because we had our node loader in place already at the start.

09:13 And with that, now we're able to properly serialize these server references and we'll be able to use that to actually make a request to the server with it. Awesome work.