Server Actions in Next.js | Nextjs 13 Server Mutations

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello and welcome I'm Dave today we will look at the new server actions in next js13 and I'll provide links to all resources in the description below I'll also provide a link for you to join my Discord server where you can discuss web development with other students and you can ask questions that I can answer and receive help from other viewers too I look forward to seeing you there next JS server actions are still in Alpha as I'm creating this tutorial and that means they could change but I've had many requests to cover server actions and server mutations so we're going to dive in and just know that if you're watching this in the future you should check the next JS docs as well because things do change and note this next JS video is not for beginners for better understanding as a beginner you should complete the next JS course on my Channel first and have a good idea of the difference between client and server components as well as an understanding of how revalidation works and all of that will help you have a better understanding as we explore an xjs server actions okay as I said server actions are in Alpha right now and they're built on top of react actions and there's a link here if you come into the docs and you're interested about react actions it will link to those as well but we've got here they enable server-side data mutations so we're talking about what server actions do so server-side data mutations also reduced client-side JavaScript and finally progressively enhanced forms which we'll talk about too I'm in vs code and I've opened a terminal we're going to use the latest version of next JS today so I'm going to say npx create Dash next Dash app at latest we'll press enter here and it's probably going to ask us a few questions as we go I'm going to call this server actions tutorial and then yes we'll use typescript yes eslint yes Tailwind yes for the source directory and yes for the app router and do I want to customize the import Alias not really but we can check what it's going to do if we go ahead and choose yes here and then it's going to use the at slash by default and that's really what I want anyway so I'll just press enter and then it's going to install our new project okay I've got the new project folder open now and let's look at the package Json so the version I'm using today is next JS 13.4.4 and if you're watching this in the future there may be a newer version but if you want to follow along and get the exact responses I do in this tutorial I recommend installing this version if you don't have it so after creating your project if you don't have 13.4.4 you might want to open a terminal and type npmi for install and then next at 13.4.4 so this would go ahead and change your version to the one that I'm using today if you don't have 13.4.4 so now let's look at the next dot config.js file and notice the app router is no longer listed in here as experimental and that's because it's now stable and that's great so once we have that and by the way that happened as of 13.4 as well but now server actions they're not even in beta yet they're currently in Alpha so they're definitely experimental so we need to add this to our next config where it has the experimental object and then we say server action is true and then go ahead and save the file now today being a more advanced tutorial I'm not going to write out every line of code I'm going to go over some code with you so I'm going to put my basic crud app a to-do list in place and we'll look at how server actions work with those mutations compared to say what we did previously in the next JS course that I put together in chapter 11 where we handled mutations in a different way okay we're back in vs code and I've added the full project and we're ready to review so let's just check out the main page of the project first you can see I'm pulling in two components an add to do and a to-do list so let's go ahead and look at the add to do component where we take advantage of a server action so I'll open that up and you can see we're importing a server action here from our library from an actions file so let's look at how it's applied in this file and then we'll look at the action itself so here we have a form now typically we would have a client component with any type of interactivity can we kind of have islands of interactivity if you will inside of our applications we can put those client components inside of server components but we of course make that interactivity a client component that's what has always been the standard but now now this has changed this is not a client component and it does have a form so we will have interactivity and it will still work notice it's a basic form here we just have the one input and then we have a submit Button as well and that's all there is to it and the form action attribute is calling the add to do server action so our main takeaway here is this is not a client component and yet the form is going to work with our server Action Now server actions can be invoked in several ways and they list three here one is the first one we have seen using the action attribute on a form and the other one here the second one is using the form action attribute on an input type here such as a button or an input type submit input Type image so on inside of a form so you can have different server actions called from this form action attribute if you go ahead and put it on say a button or something like that in your form the Third Way which will also look at at is with start transition and this uses the use transition hook of course to get start transition so this one has to be inside of a client component as we're using a hook and we're going to discuss more about Progressive enhancement but by using the use transition hook and start transition that's going to disable Progressive enhancement because it's going to require that extra JavaScript for that hook so back in vs code let's look at that actions file inside of our library our lib directory here so here's the actions file and here's our add to do function you can see it has the use server directive at the top now if we didn't have an actions file and we weren't using use server at the top say we defined add to do inside of the component we would need to put that directive use server inside of this function to say hey this function needs to specifically be called and ran on the server but since we have the use server directive at the top of this actions file we don't need to put that inside of each function so that's why you'll only see it here compared to some examples you may see that have that directive inside the function so for the function itself you can see it's receiving form data type here so we have our data for add to do then we're getting the title that's what we're actually getting for our to-do list here and then we're going to fetch our to-do's now I'm going to run Json server here this IP address 127.0.0.1 just means localhost but I'm using the IP address for it Port 3500 to do's and we're going to look at our db.json file that we'll have inside of our project when we get that going it's going to use the post method it's getting the content type application Json and then we're just sending it to do I'm giving every to do the user ID of one now because that's not so important for this example here's the title that we're creating and that we're getting from that form data it will always be false as far as whether it's completed or not when it's first created and then an ID for the to do will be assigned by our Json server and then finally at the end of this function we're calling revalidate path and if you've gone through my next JS course or you know how revalidation works that means it's saying this path needs to be revalidated and of course that's our to-do list that's displayed right there so that means the next time the data is requested it will be fresh and new data so if we look back at the docs here under server actions where it said what they provide we can immediately see there is reduced client-side JavaScript because now we have that code for add to do on the server in our server action and then it also mentions progressively enhanced forms let's look at what that means so Progressive enhancement allows a form to function properly without JavaScript and while that's kind of mind-blowing in a way that's why we're getting some comparisons now back to PHP actually but it's it's very cool here in next.js because we can also see the the update even though the JavaScript is disabled and that's what we're going to do to try it out it says JavaScript disabled here without JavaScript or with JavaScript disabled and of course that's what we'll do then it says this allows users to interact with the form and submit data even if the JavaScript for the form hasn't been loaded which they would call hydration or it fails to load so if you read further in here they talk about hydration and you could do this in a client component as well or if you had other JavaScript involved in it but of course that JavaScript wouldn't work if you disable the JavaScript but this server action will okay we're back in vs code and you can see my db.json file here it's in the top level of our file directory just like package Json and we're going to use Json server to run this as our to-do's API so I'm going to open up a terminal window then I'll type npx Json if I could spell json-server and then put Dash W for watch and we'll say watch the DB Dot Json file and we'll say Dash p for port and we'll give it 3500 Dash Capital H for host and I'll put 127.0.0.1 which is the same as localhost really but I'm just using the IP address so press enter and now this should start running it finds our to-do's and it will log any request here as well so we need to open a second terminal window and now in this terminal window I'll drag this over we don't need that so much but I'm here I'm going to just do npm run Dev to start our next JS project and this will get started on Port 3000 so we have localhost 3000 we can control click that and launch the app and here is the basic to-do list we haven't got into the updates or the to do component yet but we're talking about adding a new to do and of course we can just say new to do press enter and it's going to add that to do right now we have JavaScript enabled though so let's open up the dev tools with Ctrl shift I or if you like to right click and choose inspect or anything like that after that let's go ahead and go to the three dots up here then we choose run command you can see you could also launch that with Control Plus shift plus P I'll just choose run command I want disable and disable JavaScript comes up so just click on that and now you should see a little red X over here to the very right of your address bar and that's what we're interested in after disabling the JavaScript let's go ahead and refresh the page just to make sure we have a current load here we're running in Dev mode and now we have JavaScript disabled let's try to add something new here with our add to do function and I'll just put a hello and press enter and it still works we have no JavaScript running whatsoever right now in the browser and our server action still works and that's pretty cool and that's what they're referring to as Progressive enhancement so you can still have some of that interactivity without the dependency on JavaScript or if that JavaScript doesn't load some things will still work now we're back in vs code again we've already looked at the add to do with the server action that uses Progressive enhancement and now we're going to look at the to-do list and it's pretty basic here we're just fetching the to do's and then if we don't have any to Do's we'll say no to-do's available but if we do we're going to reverse them just so we have the latest at the top and we'll map through those reversed or sorted to do's and of course we'll use the to do component and that's where it gets a little more interesting so let's take a look at that to do component and I'll go ahead and press alt Z to wrap any code that might scroll off the screen but in this to do component you can see we are importing delete to do from the actions file that we have in the lib directory as well and then we're importing update checkbox and we'll get to that in a minute but let's look at this delete first so as we get down into this to do component we can really see besides the label which is actually holding the title of the to do as well so that's the part we read then then we have the update check box and we have a button that will delete the to do now notice this is a form but we're not using the form action attribute we're using the form action this is the form action attribute up here I should say it is the action attribute that would be on a form element that's easy to confuse as you talk about the two of them because this is a form action attribute so we are using this now this is something I didn't see represented quite so well in the docs at least in my opinion and that's because they just had a function that they would call by name like we previously did with add to do but what if you need to pass something to your function well then you usually have to use another wrapper function like an anonymous function as you see here and all server actions need to be asynchronous as well so we have an async anonymous function and then for this to work correctly we do need to put the use server directive inside this anonymous function now that's not the same as the use server directive that is used on the delete to do function that is inside of our actions file now we already used that for delete to do but still here we need this directive for this Anonymous async function and then we're just awaiting the delete to do right here and passing that to do in so this function also works with that Progressive enhancement as far as a form so we could delete something without having JavaScript enabled as well let's try that out okay we're back in the browser I don't know if you can see this little red X up here but once again JavaScript is still disabled so let's go ahead and delete this hello to do that we created if I click on the button it just deletes it it works without that JavaScript so that is also a progressive enhancement for a form and we're using that with the delete to do server action now before we move on to the update check box let's go ahead and re-enable the JavaScript because here we're going to use a transition that we talked about and that's going to need the JavaScript enabled as they noted in the documentation it will not work with Progressive enhancement so let's go back to the three dots and run command here we can type enable and we'll see enable JavaScript come up if we have disabled it so I'll just click on that now and we'll probably need to refresh because it still shows it's blocked right now so let's refresh and yes that red X goes away so after you disable or re-enable your JavaScript you should probably always refresh your app to make sure it is applied correctly and just a quick note back here in the docs before we look at our actions file once again and that is on server mutations that's essentially what we're looking at with our server actions today this is kind of a term thing just to get right in your mind because this is a server action that mutates the data and we're doing that when we add something when we remove something and especially when we update something then it says M calls read direct revalidate path or revalidate tag and all of our server actions today are calling revalidate path at the end and back in vs code we're back at the actions file we already looked at the add to do server action so let's look at the delete to do which isn't much different it just gets the ID of the to do as we send it to our Json server and then of course at the very end it calls revalidate path so not a whole lot that's different there we might as well look at the update to do server action while we're here also and it's very much the same we just passed the to do ID and then we're of course putting in that updated information which it's just flipping the completed which is a Boolean so it's the opposite of what it was before and we have revalidate path at the end so very simple functions overall and you've probably seen a to-do list before but these are our server actions now let's go back to that update checkbox component that's in our components directory so let's look at how this is a applied with used transition and you can see right away it has the use client directive at the top and that's because we need client-side JavaScript here for any hook we would use like use transition now a client component can still call a server action and we're importing our update to do server action right here so as I scroll just a little bit you can see we apply the use transition hook and then we get is pending from the hook as well as start transition you can use the is pending part of use transition in a disabled attribute if you want to so it will just be disabled essentially while the transition is taking place now for a check box we're using the on change and you can see here we have an anonymous function that then starts the transition which then itself has an anonymous function and then inside of that we call the update to do and pass the to do in and notice we're using start transition here we don't need to await the update to do as we did previously with our other function but this is the third way of calling a server action as they said in the docs because here we're having a custom invocation and essentially that's what you need to do with a check box so this will need the JavaScript enabled but then it should work in our app so let's take a look okay we're back in the browser I can close devtools now as we have JavaScript enabled and now we're just working with the checkbox here so we can check and it unchecks the box now let's see if that's saved in our Json server data so if I refresh will we get the same data yes so it was successful and of course you can check your dbjson file as well to see if that changed we can check it once again and it once again saves that data so when it reloads it's now checked and this works great and it will continue to work great as long as we're on a single page but when we go to a second page that might edit the same data and we come back to this page or go back to that page things can get out of sync we need to remember that we're working with server actions here everything we're changing is the data on the server we're not keeping any type of client-side State here and that could cause a problem let me show you what I mean so we can go to any one of the edit pages so if I went to the new to do page here and now I check that this is complete and I go back it's still not complete here on the main list page if I go that page it does say it's complete so now we have a problem and that's because one we're revalidating this path when we have that but not the other path but the other issue is what I was talking about we we are working with that data on the server but it's kind of a little known thing that next JS does have a client-side cache and you need to know the difference between hard and soft navigation hard navigation will go ahead and grab fresh data soft navigation is going to use cache data as it goes between pages and that is actually what the next link does it uses soft navigation unless we clear that client-side cache so that could be an issue if we're changing data on one page and then linking to another and if you want an even deeper dive on that I go into quite a bit of detail about that in the 11th chapter of my next JS course that's on my channel so now we're back in vs code and we're going to apply a fix so we can work with this data on two separate pages so let's scroll to the top of this file I'm going to comment out the use transition usage so it will still be there in the code if you want to refer to that or switch this component back to using the start transition but let's go ahead and apply what I'm going to now and I'm going to do a couple of different Imports here alt Z to wrap that down one you can see is the experimental use form status Hook and the other one is the use router Hook from next navigation and then underneath I'll comment out out where we defined these is pending and the start transition from use transition and instead we're going to define a router with use router and we can get pending from use form status so the easy change down here is instead of using is pending we can just use pending from that use form status inside of our disabled attribute and now I'm going to comment out this on change line just so you can keep the start transition here inside of the source code that you might want to refer to and I'll put in a different on change line here this is going to once again use an async anonymous function and then inside of this we don't need to use the use server directive because we're not making this Anonymous function a server action we're just using a server action inside of it so I'm going to await our update to do and pass in to do and this will still call our update to do server over action and after that I'm going to use router.refresh and the reason I'm using this and I'll put a note here is it updates the client-side cache in next and that's something I went into detail on in that chapter 11 of my next JS course because at the time that was something that they just had in a canary version and I showed how it was going to work in the future and we actually used that Canary version a little bit which is of course something they're still experimenting with and haven't released yet now it's available here in this version of next.js so when we call router refresh even that soft navigation that we'll use to go back to our list from the edit page should update and we should see the new data back in the browser now I'm going to refresh just to make sure everything's up to date we can check the new to do and on the edit page it has the same as it does on the list so let's go to that edit page again and let's uncheck our new to do and now let's go back to our list and on our main list it is also unchecked and that's because we're using our next link navigation right here when I click next to do's and it takes us back to the home page as well as when I click on new to do and it takes us to this page so yep back on this page if I click check and then it's done I guess what that would mean on our to-do list we've completed it let's go ahead and look and it's completed on the edit page here as well if I uncheck it's unchecked here so likewise if I check here it should be checked there and if I uncheck here it should be unchecked so everything is working as expected now however did you notice I don't know if you can tell or not on my screen but there's just a slight bit of lag when I check the box I click and then it happens and that's because this is hitting the server for that information we're not using an optimistic update we're not seeing something on our page first as then we would send the request and see if it was successful that's what an optimistic update is is we go ahead and change it in our UI that's our user interface and then if it's successful everything stays the way it is if it's unsuccessful it will revert those changes there is a way to apply that and that would make it just a little snappier so we wouldn't see that delay I think there you could actually see me click when it's checked and then it disappears in just a split second later and of course that could be longer if you're not running the this local Dev server so let's go ahead and apply an optimistic update as well back in vs code in our update checkbox component we have one more import to now use at the top and that's going to be the use optimistic hook that is now available and you can find documentation about this although there's not much right now but you can find it on that server actions page in the docs hopefully in the future there will be some more examples I'm going to use something that's simpler than the example that they actually show in the docs so scrolling down where we begin to use our other hooks after we've imported use optimistic we can apply it here now this looks a little complicated at first so let me break it down so we have our optimistic to do because we are passing in a to do to our update checkbox component right here that you see so this will represent that to do but it's an optimistic to do and then we have ADD optimistic to do which is a function and if we look at the type if we break this down here and come down it's is actually a reducer here I believe we have the pass-through of the to do then the reducer so you could do something more complex and we may do something dedicated to optimistic updates in the future maybe a video about that but right now this should be fairly easy to apply for to do so our state is a to do and that's being passed in first that's that pass-through data and then what is changing is just that completed field that's a Boolean so all I'm doing here which would be really the reducer function that it's receiving these because this was the state before so here's the beginning of the reducer function and then inside the reducer function I'm just creating a new object here for the to do so we're spreading the state which was the previous to do then we're overriding the completed but now in our jsx we're going to need to change a couple of things too one would be our checked line here so I'm going to comment out the previous one and I'll put in the new one now we're going to use the optimistic to do data so we'll have Optum Mystic to do dot completed instead of to do not completed because this is what is displayed inside the UI so that's important now inside the on change here we're going to use that optimistic or ad optimistic to do function and we're just going to make it the opposite of the to do completed now here we're using the original to do because this isn't data that is displayed the optimistic part is what we want to essentially display before we send the update to do server action here so we're adding the optimistic to do first into the UI then we're calling the server action and then finally we're refreshing that client-side cache here so let's save this and now let's go back to see our app in the browser hey we're back in the browser I'm going to give it another refresh just to make sure we have everything the way we expected and now when I click new to do it should be fast and it is there's no wait at all so we're essentially applying that check mark before the request is sent and if it's successful which it is then it stays if it's not successful it should revert at least that's my understanding of how this use optimistic hook should work and I hope to find more information and examples on that soon this is all very new remember these server actions the server mutations are all in Alpha right now so things can change so I guess the last thing I would say is always go back and check that documentation remember to keep striving for Progress over Perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 5,531
Rating: undefined out of 5
Keywords: server actions in next js, nextjs, next.js, next js, server actions, server mutations, progressive enhancement, next.js actions, react actions, server actions form, form action, formaction, server actions startTransition, nextjs server actions, next.js server actions, server actions in next.js, server actions in nextjs, next js server actions, next.js server mutations, nextjs server mutations, nextjs 13, next.js 13, next 13, next 13 server actions, server actions next js
Id: BmUsDuLO598
Channel Id: undefined
Length: 28min 2sec (1682 seconds)
Published: Fri Jun 02 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.