
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
Complete source code available till this point of lesson is available at
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
In this lesson, we explore server actions in Next.js, which provide a quick and efficient way to execute code on the server. The demo includes creating a Next.js app, setting up a mock database, implementing helper functions for data operations, and utilizing server actions for ticket management functionalities like creating, deleting, and updating tickets.
use server
directive.00:00:02 This demo will be all about server actions, Next.js' quick way of executing code on the server.
00:00:08 So I've created a new folder called server actions dedicated strictly to explaining how these asynchronous functions truly work and when you might want
00:00:18 to use them instead of using API endpoints.
00:00:21 So let's dive right in.
00:00:23 First, I'll create a new Next.js app by running mpx create-next-app add latest and dot slash to create it in the current repo.
00:00:34 It's going to ask you a couple of questions, so just press enter for all of them as we'll go with the default options.
00:00:40 Once everything gets installed, open up your file explorer and let's clean our app a bit.
00:00:45 First of all, I'll remove everything from globals.css besides Tailwind CSS imports.
00:00:51 I'll also delete all the boilerplate code from the page.tsx and in the return statement I'll leave just a single piece of text that's gonna say something
00:01:00 like hello server actions.
00:01:03 There we go.
00:01:04 Now, just to verify this works, let's open up our terminal and run npm run dev to explore this on localhost 3000. There we go.
00:01:13 That is looking good to me.
00:01:14 So going back here, let's create a new folder outside of the app folder, and let's call it lib, as in library.
00:01:21 Within the lib, we can create a new file called database.json.
00:01:26 And within that database, you can add a list of dummy data.
00:01:29 In this case, let's say that we're mocking a database of some kind of tasks that we want to resolve.
00:01:35 So I'll open up an object.
00:01:37 Let's say that we have some kind of a weird structure where each task is labeled by a number.
00:01:42 So in this case, it's going to be one.
00:01:44 And within it, we can also give it an ID equal to one.
00:01:48 It can have a name of something like fix next.js API route bug.
00:01:56 There we go.
00:01:57 We can also have a status of something like open, so it can either be in progress or open or fixed, and it can have a type.
00:02:07 In this case, let's say that the type is a bug.
00:02:10 And since we're working with JSON, we must not have an ending comma right here.
00:02:14 Now I hope my cup pilot will auto fill this for me.
00:02:17 There we go.
00:02:18 It automatically knows that I want to add some more open tickets.
00:02:21 And in this case, it just says name, add Tabscript support, status open.
00:02:26 And this is a feature because we want to add something and not fix something.
00:02:30 Of course, you can continue adding some imaginary tickets to our list of tasks that we want to accomplish.
00:02:36 Add Tailwind CSS support, ESLint support, and let's see, add post CSS support.
00:02:42 Okay, it looks like he just wants to add stuff and not fix stuff.
00:02:45 But sometimes the world is not all sunshine and rainbows.
00:02:49 So we might want to fix some stuff.
00:02:51 Like let's change this over to fix hydration warnings.
00:02:58 Yep.
00:02:58 Those happen often in Next.js.
00:03:01 So this will be a bug.
00:03:03 And let's just add one more.
00:03:04 That's going to be seven.
00:03:05 Add the React 19 support.
00:03:08 Good.
00:03:09 So now we have a mock database of seven different tickets, some of which are features to be added, some of which are open bugs,
00:03:17 and some of which are fixed.
00:03:19 Great.
00:03:19 Think of this as your own self-hosted database, which typically would be on some cloud over on Postgres or maybe MongoDB Atlas,
00:03:27 but for now it is right here in your file explorer.
00:03:29 But the whole goal of this demo is not to teach you how to create your own mock database.
00:03:35 It is to teach you how to work with server actions.
00:03:38 So let's create another file within the lib folder and let's call it helpers.ts.
00:03:44 Here we'll add some helper functions to help us read and write data from the JSON file.
00:03:50 So I'll write something like export function read file.
00:03:56 And once we try to read it, I will return json.parse fs which is going to come from the file system dot read file sync to which we can pass the file path
00:04:12 And it's going to be a UTF of 8 format.
00:04:15 In this case, FS stands for file system.
00:04:18 And typically this is something you would only have access to when you work with a real server like ExpressJS or maybe HONO.
00:04:26 But in Next.js, you can just say import FS from FS and you will have access to it.
00:04:32 In this case, our file path will be static.
00:04:35 We always want to go to the same one.
00:04:37 It's going to be forward slash lib, forward slash database dot JSON.
00:04:42 We can create a similar function for writing data.
00:04:45 So that's going to be export function, write file.
00:04:51 which is going to accept the data, which we want to write of a type record.
00:04:55 That's going to be of a type string and ticket as well.
00:05:00 And here we can say fs.write file sync, which will accept the same path.
00:05:07 That's going to be a lib database.json and then json.stringify data null two.
00:05:15 That's just the format in which we want to write the data.
00:05:19 When it comes to the ticket, this is actually a TypeScript interface.
00:05:22 So right here, we can say interface ticket will contain the ID of number, a name of string, a status of string, and a type of string as well.
00:05:36 It's the same thing that we passed over in our database.json, whereas each one of these tickets has that same exact structure.
00:05:44 And one small optimization we have here is that we are duplicating this string right here.
00:05:49 So we can actually extract it.
00:05:51 const file path is going to be equal to a string of lib database.json.
00:05:57 And now in both of those places, we can simply refer to a file path.
00:06:04 Good.
00:06:05 So now you created two utility functions that allow us to read from that mock JSON database and write to it.
00:06:13 And one thing that I want to point your attention to is that this helpers file is right now just a regular everyday file.
00:06:21 It's not doing anything special, which means that you can also call it from your frontend.
00:06:26 You're exporting this read file function.
00:06:28 So if you head over to your app, page.tsx, and decide to call this read file right here at the top by importing it from lib helpers,
00:06:39 you can totally do that.
00:06:41 And in this case, it would actually call it from a server component because every component in Next.js by default is a server component.
00:06:50 So if you decide to do this, that would be totally okay.
00:06:53 But if you later on decide that you need to turn this into a client component by assigning it a use client directive at the top,
00:07:00 that would not be okay.
00:07:02 because file storage is something that exists only on the server side.
00:07:06 So this would, of course, lead to an error.
00:07:09 And to prevent this unintended client use of server code, you can use a package called server-only.
00:07:16 We can install it right here by heading over into the terminal and running MPMI server-only.
00:07:24 This package will give you a build time error so if you ever accidentally import one of these modules into a client component,
00:07:31 you will automatically be notified and hopefully you'll be able to fix it on time so your users never end up seeing the error that you make in the code.
00:07:40 The only thing you have to do to make it happen is head over into the helpers file or whatever file is using the server code functionality.
00:07:49 And at the top of that file, say import server-only.
00:07:54 If you do that, now you will be getting a different kind of error saying invalid import server only cannot be imported from a client component module.
00:08:03 It should only be used from a server component.
00:08:07 So now you know that you have to head over back to your page, remove the use client import, and your app will work again.
00:08:14 Great.
00:08:14 Now that we have the helper functions out of the way and that you know a bit about how Next.js can access server-side modules and how they only need to
00:08:22 be called on the server-side, let's actually create a page that'll allow us to create a new database entry.
00:08:30 In this case, that is a product management ticket.
00:08:32 So let's create a new file in our File Explorer by heading over to App, creating a new folder called Ticket, because we're using the file-based routing.
00:08:43 Within Ticket, we can create a new one called Create.
00:08:48 And within create, in this case, I'll create another folder called client.
00:08:53 And within client, I'll create a new file called page.tsx.
00:08:58 And within here, we can write the code that allow us to submit a new ticket.
00:09:02 In this case, I'll leave the code for this file right below the lesson.
00:09:06 So you can simply copy it and paste it here.
00:09:09 The actual JSX is not what matters here.
00:09:12 Learning about server actions and server-side concepts is.
00:09:16 But don't worry, I'll explain everything from scratch.
00:09:20 Starting off, we have a simple client-side rendered page.
00:09:24 Why client-side?
00:09:26 Because we're using a form within it.
00:09:28 And that form has an onSubmit property, which means that something happens on click.
00:09:35 And clicks can only happen in the browser, right?
00:09:38 So that's why we have to turn this into a client-side component.
00:09:41 Here, we have a simple form that has some Tailwind CSS styling, and it has inputs for tickets text, type, and a button to submit.
00:09:50 In the handleSubmit function, we're trying to access the form data, and then we're preparing to call the server action here that would actually submit
00:10:00 the data.
00:10:00 So now is the time that we actually write it.
00:10:02 Head over into the lib folder and create a new file called actions.ts.
00:10:10 This will be your first server action.
00:10:13 Within every file that contains server actions, you'll have to add the use server directive at the top, because server actions can only be called on the server.
00:10:22 Now let's export async a new function called createTicket, which will accept the form data of a type formData.
00:10:34 And now we can create the ticket by first getting its name from the formData.
00:10:40 We can destructure it by saying formData.getName as string.
00:10:46 And we can also do the same thing for the type by saying const type is equal to formData.getTypeAsString.
00:10:55 Now we can read all of the tickets from the file by saying const tickets.
00:11:01 is equal to read file and this can come from our helper functions just like this once we do that we have to get the id of the last ticket which we can
00:11:12 do by saying const id is equal to object dot keys tickets dot length If it exists, then we can take the math.max.
00:11:26 We can spread the object.keys of tickets, and then we can run the .map on it.
00:11:34 based on the number, just like this.
00:11:36 This will give us the maximum index in that array.
00:11:39 And then we can just run plus one outside of it to increment it by one to get to the last one.
00:11:45 Else, if we don't yet have any IDs, we can just set it to one by default because zero plus one is one.
00:11:53 This is a bit of a complicated function to just get the last index, but that is because the data in our database is a bit complex.
00:12:01 It's not typical.
00:12:03 It seems like it could be an array, but actually it's adjacent object where keys are strings of IDs, and then the values are actual data points.
00:12:13 Sometimes the data you'll be getting from backend is unfiltered, unclean, and just stinks.
00:12:17 But you'll have to work with it, so you might have to do some tweaks like this.
00:12:22 In any case, what this does is it gives you the ID of the next ticket that is about to come.
00:12:27 So if we have seven, now this should be eight.
00:12:32 Finally, once you have that, we can say tickets and then ID, in this case 8, is going to be the new ticket that's going to have this ID.
00:12:42 It's going to have the name, which we pass.
00:12:44 It's going to have a type that we pass and it's going to have a status of open.
00:12:50 Finally, we can write file.
00:12:53 This is coming from helpers and to it, we can pass the new tickets.
00:12:57 So this should help us write into the database.
00:13:00 Instead of simply writing here and the reading from the file, you could perform any kind of actions by reading and writing to an actual MongoDB or Postgres
00:13:10 or whatever else database.
00:13:12 I think you get the idea.
00:13:13 Now we can actually call the server action within our page.
00:13:18 So if I head over to our create client page, we have the form data.
00:13:24 And the only thing we have to do is call this server action by saying await create ticket coming from lib actions to which we have to pass the form data.
00:13:37 Now back in the browser, if you head over to ticket, create client, You should be able to see a new ticket form that allows you to type in a name of the ticket.
00:13:48 For example, learn server actions and type will be feature.
00:13:56 Let's submit it.
00:13:58 you get redirected back to home, but hopefully we can now see something in our database JSON.
00:14:05 If you head over here, you can see that we have successfully used a frontend Next.js application to make changes to a file in our file system.
00:14:15 So it's not really just frontend only, it also did something with a local file system, which makes it more similar to some kind of a backend server.
00:14:24 Pretty interesting, right?
00:14:25 Now, how the fuck did this work?
00:14:28 We are right within a client component, right?
00:14:31 Yes.
00:14:32 It says use client right here at the top, and we are using a handle submit function, which is typically always rendered on the client side,
00:14:41 not to mention that we also have a client rendered form.
00:14:44 So how did this server action execute?
00:14:48 Well, it did because within it, we added the use server directive, which means that no matter from where it is called, it'll always be executed on the server.
00:15:00 And I can prove that to you by heading over to Next.js documentation and heading over to convention part.
00:15:06 where it says that a server action can be defined with the React use server directive.
00:15:12 You can place that directive at the top of an async function or at the top of the file to mark all exports of that file as server actions,
00:15:22 which is what we have done.
00:15:24 So basically, you can add it at the top of the function itself or at the top of the file.
00:15:29 Now here's the thing, to call a server action in a client component, create a new file and add the use server directive at the top of it.
00:15:38 All exported functions within the file will be marked as server actions that can be reused in both client and server components.
00:15:46 Just like what we have done right now.
00:15:49 I hope that makes sense.
00:15:50 So server actions are super versatile because you can call them both from client and server components and they will always be executed on the server.
00:15:59 Pretty cool, right?
00:16:00 Now, let's head back over to our homepage by heading over to app, page, and let's modify it to display all of our tickets so far so we don't have to manually
00:16:11 head over to the database.json file.
00:16:14 Over here, we won't be using server actions to make mutations.
00:16:18 And that is what they're currently most known for.
00:16:21 It says here that they're used to handle form submissions and data mutations in Next.js applications.
00:16:28 But many people on the internet say that they not only use server actions to perform data mutations, but also to do data fetching because they're so convenient.
00:16:39 Robin here says that, so far, I did not have any problems with these restrictions because using a server action for data fetching in a client component
00:16:48 only happens occasionally.
00:16:50 However, I'm curious to see how the official recommendation will evolve in the future.
00:16:55 And even the Versel team is more interested in seeing how its usage will go.
00:17:00 One person from Reddit asked the Versel team on Discord to see if he could use server actions to fetch data.
00:17:07 And while it is possible, they don't encourage it.
00:17:11 But the response was a bit ambiguous.
00:17:13 They said that they'll see how the community will start adopting those server actions and maybe they make some changes then.
00:17:19 So for now, let's not use the server actions for data fetching, even on the server side.
00:17:25 Let's simply use a React server component.
00:17:28 Doing that is super simple.
00:17:30 Once again, you can find a second block of code below this lesson.
00:17:35 Simply copy it and paste it right here.
00:17:37 For a second, let's head back over to our helpers and let's export this ticket interface so we can import it here as well.
00:17:46 And then I can explain this file.
00:17:47 As you can see, this is just a regular server component.
00:17:51 And since it is, it allows us to call this read file helper.
00:17:56 or you can think of this as a database call.
00:17:58 After that, we simply get the values and we can map over them and present the data to the user.
00:18:04 If you scroll down, you'll also see a link that allows us to create a new ticket.
00:18:09 You'll see that there are two links.
00:18:11 One pointing to create a new ticket from the client side, which is the file we have created just before.
00:18:17 That's the one under page, ticket, create, client, where we use the form to submit a ticket creation.
00:18:24 And then we called a create ticket server action from the client side.
00:18:28 But soon enough, we'll also create a new one that'll be done completely on the server.
00:18:33 But for the time being, if you head back, the good thing is that now we can officially see all the tickets.
00:18:39 And at the bottom, we can now create another ticket using the functionality we have tested before.
00:18:44 Next on the list of things we have to do is add the ability to delete a ticket.
00:18:49 So let's head over to our Lib.
00:18:52 actions and let's create a second server action in the same file and we can call it delete ticket so export async function delete ticket which will take
00:19:06 in the id of the ticket it'll read all the tickets by using the read file and finally we can simply say delete tickets of that specific ID and we can write
00:19:18 to the file by passing the new updated tickets with one of the tickets deleted.
00:19:23 Now let's head back over to our homepage And we have to add the functionality to delete each individual ticket.
00:19:31 We can do that by heading over right here below the link.
00:19:36 And I'll create a new form.
00:19:38 Within the form, I'll create a new button.
00:19:41 And this button will be of a type submit with a class name of text-red-500.
00:19:50 And it'll simply say delete.
00:19:52 Now, if you had here, you can see a delete button.
00:19:55 Now, to make this functional, we can use React's new functionality.
00:19:59 Specifically, a new prop that they now allow to be passed into a form component called action, which is either a URL or a function.
00:20:09 When you pass a function to the action prop, the function will handle all the form submission.
00:20:15 And this function may be asynchronous and it will be called with a single argument containing the form data when submitted.
00:20:22 In other words, it allows us to render and execute a form on the server.
00:20:26 Pretty revolutionary stuff.
00:20:28 Let me show you how it works.
00:20:30 You simply need to pass in the action prop.
00:20:33 Here, you can define a new asynchronous callback function, which is going to look something like this.
00:20:40 At the top of it, you need to add the use server directive.
00:20:45 And then here, you can call any server action, like await, delete, ticket which we created in the actions file and you can pass the ticket id and if you
00:20:55 head back over to your browser and click delete on this first one which says fix nextgs api route bug oh it seems like nothing happened try reloading no
00:21:06 it's still there and one of the reasons why it didn't work could be because we missed adding something into this deleteTicketServer action,
00:21:15 and that something is the revalidatePath functionality.
00:21:19 To it, you need to pass the path which you want to revalidate, which means that the data on that page will be refreshed.
00:21:27 In this case, you're deleting something from the home page, so you want to revalidate that path.
00:21:31 Now, I've spoken with Lee from the Versel team, and he said that Next.js might be renaming this in the future.
00:21:38 So if that happened, feel free to look down into the lesson, and I'll provide you with the links to the updated docs for the revalidation.
00:21:45 It might be called something different in the future.
00:21:48 Now, if you head back and click delete on a couple of these, you can see that they're getting deleted.
00:21:53 I noticed that for the first one, it's not actually deleting it.
00:21:56 It might be because of the way in which we created this database JSON.
00:22:00 Let's try to see why that is by heading over to the database JSON.
00:22:04 You can see that these other ones indeed have been deleted, but the first one is still there.
00:22:09 What if we try to get rid of it manually?
00:22:11 Save and reload.
00:22:13 Yep, that works.
00:22:14 And the other ones can be deleted.
00:22:17 Great.
00:22:18 So now the deletion works and we can try to create a new one.
00:22:22 Let's say fix next.js API routes.
00:22:26 That's going to be a type of bug and submit.
00:22:30 There we go.
00:22:31 Everything works.
00:22:32 So now you've not only learned how we can call server actions from client components.
00:22:39 Like we have done here, you basically just call them, but you also learn how you can call server actions from server components,
00:22:46 such as from the homepage, by creating a server rendered form using React 19 functionalities, and then calling it like this.
00:22:56 Now, just to recap on what you've learned, similar to what we did here with the lead ticket, we can also create a form that works without any client-side
00:23:05 JavaScript to create that ticket.
00:23:07 So let's create a new file right here under ticket, create, page.tsx.
00:23:15 So this time we won't be under the create client.
00:23:18 It'll be just create page.tsx.
00:23:21 Here, I'll pass to you another block of code down below this lesson.
00:23:25 You'll notice that it is super similar to our client render component.
00:23:29 I can even put them side by side right here.
00:23:33 So you can compare the differences.
00:23:35 The same thing is that they're both using this createTicketServerAction, but the one on the left doesn't even need this handle submit functionality.
00:23:43 Here, we just pass the createTicketServerAction as a function to formsActionProp.
00:23:50 It is as simple as that.
00:23:52 Everything else is exactly the same.
00:23:54 Now, while this may work, it won't do the redirect properly, as here in the create ticket, we're just writing the file, but we're not redirecting.
00:24:03 Before, we were doing that right here on the client side, because we had the router functionality, because we were in the browser.
00:24:10 But how do we redirect from the server side?
00:24:13 Well, we can introduce something known as a server side redirect.
00:24:17 It is very simple.
00:24:19 Just after we write to the file, you can call redirect coming from next navigation, and you can redirect to forward slash.
00:24:27 So now, even on the client side functionality, you can remove this router push because the create ticket itself automatically reroutes to the homepage.
00:24:36 Now, let me show you something cool.
00:24:38 If I head back over here and try to create a new ticket, I can write something like learn server actions.
00:24:46 It'll be a feature.
00:24:49 And I submit.
00:24:51 That works well.
00:24:52 They get created immediately and we get redirected.
00:24:56 We can do the same thing with create a new ticket client.
00:24:59 There wouldn't be so many differences, like create a new ticket, that's going to be a feature, and submit works very well.
00:25:08 But what happens if we try to submit it without having JavaScript on the page?
00:25:14 I know nowadays that's a rare scenario, when don't you have JavaScript running, but it could happen, right?
00:25:20 So, if you head over to your Developer Tools, press Ctrl or Command-Shift-B, and then search for JavaScript, you can press Enter under this Disable JavaScript tab,
00:25:30 which will disable JavaScript.
00:25:32 Now you can try to resubmit the form, like testing this client form.
00:25:38 And let's say this is a bug and click Submit.
00:25:41 And if we head back over to the homepage, you cannot see this new ticket for which we have just submitted the form.
00:25:49 It didn't work.
00:25:51 But if you head over to create a new ticket on the server side, keep in mind JavaScript is still disabled.
00:25:57 I'll say testing, testing.
00:26:01 and I'll rate this as a bug and click Submit.
00:26:04 Check this out.
00:26:05 The redirect work and the ticket got actually created.
00:26:10 So now we can turn our JavaScript back on because we don't want to live without that.
00:26:15 This is JavaScript mastery after all.
00:26:17 But you get the idea.
00:26:19 If JavaScript is not working or if whatever else is happening, you need to allow your users to perform the action.
00:26:26 So that's why doing things on the server is preferable whenever possible, of course.
00:26:32 Pretty cool, right?
00:26:33 And this is it.
00:26:34 That's all that we needed to fully understand how server actions work.
00:26:38 If you want to get some extra assignment for testing, try to implement the functionality to update a ticket.
00:26:45 You'll need to create a new page under tickets.
00:26:49 Update, and then ID, which is going to be a dynamic route, of course.
00:26:55 And under ID, you can create a page.tsx.
00:27:00 Within here, you can implement the updating functionality for each individual ticket.
00:27:05 Of course, this is only if you want to get some extra practice.
00:27:08 The delete, get, and post were already enough for us to understand how server actions truly work behind the scenes.
00:27:15 But if you want to make this happen, you can implement a form similar to the submit form.
00:27:19 That will allow you to get some data.
00:27:21 That form would look something like this.
00:27:24 Same as what you had before, but here you would actually call the update functionality.
00:27:29 So you would then have to head over to actions.ts and create a new server action.
00:27:35 So if you want to try this out on your own, pause this video and try it out.
00:27:40 The goal of this is not for you to just watch, even though this is just a demo and I have plenty of real projects where you can truly use everything that
00:27:48 server actions offer.
00:27:49 But still, if you want to try it on your own, pause the video and implement the update ticket server action right now.
00:27:56 I'll provide the solution in three, to one.
00:28:00 There you go.
00:28:01 That would look something like this.
00:28:02 You get access to all of the values, pass from the form, you read the file, and finally update the tickets.
00:28:09 Now, back in the update page, you can simply call await update, ticket, to which you pass the ID, which you first need to turn into a number,
00:28:19 and then pass the full form data.
00:28:21 Important thing to mention here is that this is a server-side form as well, similar as to with the lead.
00:28:27 And you can see that because we're passing this handleSubmit function as the action prop of the form.
00:28:33 Okay?
00:28:34 So that's where we're using a Next.js navigation redirect here, instead of using something like router.push, because that's a browser functionality.
00:28:42 You have to be mindful of whether you're on the client side or the server side.
00:28:47 And I know that this can take some time to fully settle so you understand what's happening behind the scenes, but once it does,
00:28:54 once you go through it a couple of times, trust me, it'll be super clear.
00:28:59 So what we have just done is now we can click on each one of these, such as fix next GSAPI routes.
00:29:05 And let's say that the status is now closed.
00:29:10 And I'll also turn it into a feature and click update.
00:29:14 So now if I search for fixed Next.js API routes, it's a closed feature, which means that the update is working and we're seeing the changes implemented
00:29:24 in real time through this server rendered page with a server rendered form using server side, server actions.
00:29:33 So let me summarize.
00:29:36 Server actions are mainly, for now, used to perform mutations from client side as they make a POST request.
00:29:45 But you can also use them to make GET requests, even though it's not necessary, because typically when you're getting something,
00:29:51 you are already within a server component.
00:29:55 Why?
00:29:55 Because when you're submitting something, you typically need client functionality.
00:30:00 But we have also proven that not to be the case by using the new React 19 form function, allowing us to submit things using a form even on the server side.
00:30:09 So that's the first thing.
00:30:11 Secondly, if you want to call server actions from the client side, you'll have to create a separate file with use server written at the start of that file.
00:30:20 That's going to look something like this.
00:30:23 lib actions DS, use server, export async function mutate.
00:30:29 And to call server actions from the server side, you can just write use server at the top of the function body.
00:30:36 So that's going to look something like this.
00:30:39 Async function handle submit, use server right at the top.
00:30:43 And that's it.
00:30:44 Now you know everything there is to know about server actions and how we can call them within server components, function components,
00:30:53 even how we can pass them as the action prop to the form component, and more.
00:30:58 And if it's still not clear what server actions are or how do they work within real applications, I'll also leave a link to an additional lesson I've created,
00:31:07 which is another 40 minutes of content where we'll first go over the animated theoretical parts of how server actions work,
00:31:15 That's going to look something like this, like in a practical way, you can understand how, what server actions are, how they work and how to use them within
00:31:25 your own apps.
00:31:26 And then you'll build and deploy a very small app that allows you to fetch data using server actions that we discussed.
00:31:34 and I'll even throw in some frame motion for animations.
00:31:36 So, if you need that quick refresher and some animated visuals, I'll leave the link to this additional guide down below.
00:31:44 With that said, great work coming to the end of this lesson.
00:31:48 I hope you learned a lot, and I'll see you in the next one.
00:31:52 Great work.