Build Modern Next 14 Server Side App with Server Actions, Infinite Scroll & Framer Motion Animations

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what the heck is a server action and why do I even need them if nextjs has API routes won't they just make my code an entangled mess and break the engineering principle called separation of concerns or even worse is nextjs becoming PHP have you been losing sleep lately over these questions if so I've got you covered in this video not only will I answer these questions but I will also guide you in building an app that answers them in a practical way so you can finally understand what server actions are how they work and how to use them in your apps will build and deploy a responsive anime website that shows an infinite list of various anime with framer motion and using nextjs serers side features and before we build it let's do a quick crash course on server actions even before the crash crash course I need to let you know that the Black Friday sale on the ultimate NEX gs14 course is here you can get 30% off the original price and it even Stacks with regional pricing also we just added two special bonuses to the course one a guide to Advanced features powerful libraries and robust security practices in next1 14 and the other most common nextjs FAQ answered both of these bonuses offer short and precise explanations with the ability to dig deeper into it with manyi projects so if you want to enroll check it out before the Black Friday sale ends this Monday and join Over 2,300 developers who have already joined and adore it go to jm.pro next4 or click the link in the description to enroll but with that said back to the the crash course not that long ago right after the release of server components nextjs released server actions server actions are functions that run on the server but we can call them like any other normal JavaScript functions to create these server actions all you have to do is use the use server flag so a common example of server actions you may have seen on the internet might look something like this there is a client component called app in which we have a form that's calling request username function which seems to be using that use server flag so a client component is making a call to a function that is stored inside of a server what the heck is happening here it means that this isn't just a function call a request was actually made to the nextjs API to call that function it's just that we can't see them as nextjs hides it for us so let me take you to the deployed side of the application you'll build in this video you see after the initial load so the first time the site loads the next data in the network tab you'll see Local Host click on it and you'll notice that it's a post request with some payload and it's specified as next action under the hood whatever we write inside a function labeled as use server is turned into an API with the post method that sounds a bit confusing right not a lot of people talk about this but today you and I are going to dig deeper in short we're doing this we're making a regular fetch API call from client to server but nextjs abstracts this from us so you might think if both are the same thing why should I ever use server actions well first of all your code is going to have less code code right we need to write a lot more code for an API route versus a server action with server actions we focus on the business logic getting data from the form and doing the database operations with API you not only have to make a request from a client yourself but you also need to create an API on the server where you listen to these requests from a client double the work also there's no API we don't have to create any kind of apis with server actions since NEX GS will handle it automatically for us that's great but this is also a problem with server actions as you have seen all that server actions basically do is make a post request but we don't really have control over that request nextjs does it for us so we could run into some compatibility issues in case you're developing apps on desktop or mobile in that case using server actions doesn't make sense at least right now that's because updating a server action endpoint multiple times for desktop and mobile and web is both risky and unnecessary hopefully versell does something about that soon but if you develop just web apps you should be good another reason why we want to use server actions is that they are going to result in less client side code now that we're handling the database calls or business logic directly we can ship less client side code this would mean that server actions would work even if someone disables client side JavaScript to show you what I mean let me take you back to the app we're building today for now I will comment out frame or motion animation on the cards as they do need client side browser interactions but once we disable that everything is server side so we can open up developer tools disable JavaScript from preferences and reload you'll see that we can still see the first few elements in the page Isn't that cool but what about that infinite spinner well it won't show up as its logic depends on browser functionality it's a pure client component so what's the point of all of this well understanding this means that we're shipping less client side code offloading the burden of processing client data will mean our pages will load faster they'll respond better and thus server engines will favor them it will further improve core web vitals crawl budget craw ranking and ultimately the user experience if your website works well it could also mean more people doing what we want them to do like buying something or signing up and finally another big Pro of using server actions is improved DX which stands for developer experience by directly focusing on the business business logic we can ship code faster and therefore benefit ourselves with some well-needed rest or downtime like watching anime reading books or playing some games or even the client or company we're working for as you'll be able to develop things faster in a better way but even after all of this you still might have some questions let me take a guess are you wondering if there is only one way of using server actions like through client components the answer is no we can use server actions inside server components as well how well the same way as before we declare a server component as you can see we don't have the used client at the top and we simply fetch a used server action called Fetch anime now you might be thinking wouldn't that be a post method from a server component for fetching anime well let's go back to our application and see what's happening if you if you open up the network Tab and find Local Host again you'll see that it's a get method where we're getting the whole HTML page so since the function we're using is a server action and so is our whole component page it's a server component everything gets executed on the server side and turned into an HTML page which is then served to the user in this case the client it all happens on the server but if you notice the very first infinite scroll loader and see the network tab you'll see that indeed it is a post method requesting another set of documents from our API this infinite scroll loader is a client component where we're calling the same server action we'll see that live in a few minutes but the whole point was that you can still use server actions to get a list of data however they're more powerful than that server actions allow you to do mutations meaning create update and delete actions on top of the typical read together making up the complete crowd operation set o that was a lot right but hopefully now you have a better idea of how server actions work at least in theory but finally the moment you've been waiting for is here let's see how we can use those server actions in both client and server components as we've learned as well as Implement infinite scroll and use framer motion on top of that grab a cup of coffee and let's do it now as I've hinted at the start to demonstrate all of these great nextjs Concepts and features you'll build anime Vault now whether you are an anime fan or not it doesn't really matter think of these as cards as documents of sorts some data that's coming back from a database that you have to load in a nice Manner and then animate notice how smooth it is they slowly load one after another and you can keep scrolling indefinitely that's what you'll build and on top of this you'll be able to learn great Concepts so not to waste any of your time into to focus on what truly matters which is mastering infinite scrolling server actions and more I prepared the entire repo here for you with three different branches to get started you'll download just the main branch which for now just has some static data right here no API integration no logic no server actions nothing and then together we're going to build on top of that so go to code download it using GitHub desktop or simply copy this URL once you do that open up an empty Visual Studio code editor go to view and then terminal then type get clone paste the link and then type the folder name in this case we can do anime volt press enter it's going to clone it press CD anime Vault move into it and then type code dot this is going to open up a new Visual Studio code window right there you can close the old one and make this go full screen as you can see this is a typical nextjs application here we have the app folder which is the most important folder of our nextjs app for you specifically I have also prepared theore dat. s which is a simple array of about 20 or so animes right here after that we also have our favicon we have our global. CSS and then we have our layout within the layout we import the hero as well as the footer hero is typically known as a header the first thing that you see inside of an application we have a font some metadata and we just show the children within it here the children typically refers to whichever page we're currently on and in this case it's always going to be this page right within the app as that's the only page that we have right now it might be a bit hard to read because there's a lot of red squiggly lines happening so what do you say that we open up our terminal and then run mpm install this is going to install all of our dependencies and when I say all of our dependencies it sounds a bit scary because it sounds like there's too many but there really is is not if you go to our package.json you can notice that this is as Bare Bones as it gets we have react version 18 react Dom 18 as well and then nextjs 14 plus as well as some Dev dependencies like typescript so we're going to do this all from scratch now another thing that might look a bit weird and let me Zoom this out a bit is that we have those three dots right here this is a cool new extension that I found that hides your Tailwind classes when you don't want to see them but only when you click them it's going to show them to you in case you're wondering the name of the extension is in line fold great with that said let's go ahead and run mpm run Dev and let's press control click to open it up on Local Host 3000 and we are ready to explore the diverse Realms of anime magic or are we if we scroll down we can see all of the anime here but can we really as you can see we have this loader here and it seems like our app is broken but it's not really broken it's just waiting for you to learn how to do server actions and then Implement them on this app and hopefully many many more in the future so that's exactly what we're going to do next we're going to transition our app from this basic demo data onto real API data fetching using server actions so to start implementing our server actions we're going to create a new file called action. TS right here within our app within here I'm going to use the use server directive this means that whatever is written in this code will be executed as a server action then the only thing this file is going to have is going to be one function const fetch anime and then it's going to be just a typical Arrow function this function is going to have only one goal and that is to make a call to the API and return the data so we can say something like const response is equal to a weight of course since we're using a weight we have to make this function asynchronous and we can say fetch fetch is just a built-in JavaScript function to fetch data from a apis or websites and we can pass in a URL which we want to fetch from in this case we can type it out together it's going to be https colon SL SL shikimori okay that's a good one1 SL API SL Animas with an S at the end and this is it this is the barebones API so let's try fetching this first and see what it returns we can do a cons data is equal to await response. Json whenever you're using fetch you have to rund the. Json to extract the data from it and finally we can return the data as simple as it gets now let's immediately console.log the data right here before we return it our app is running on Local Host 3000 we are using this fetch anime but we're not going to see any kind of conso log because we have to use it somewhere this right here is just a function declaration not a function call so that means that we have to export this function by running the export keyword in front then we can use it somewhere and in this case it's going to be within our primary homepage right here so what we can do at the top is say cons data is equal to await fetch anime and we can immediately import it right so and make a call or even simpler for now we don't even have to declare it to a specific piece of data we can just call it that's the only thing we want because we're after this conso log of data so let's open up our terminal and immediately you can see that it called the API and it returned I think the first anime that's there just a single one with the ID or maybe it's even a random one so if I do it another time now it's it gives me the same one so it Returns the first one in a list but now we wanted to give some additional pieces of data right here so let's modify our API call we can do that by passing some query parameters you can do that by adding the question mark and then say page is equal to for now we can set it to one but we can be smart ahead of time and immediately know that this is going to be some kind of a function parameter that's going to be coming into this function so we can say page of a type number and then here now we can turn this into a template string and we can use this variable off page alongside page we also want to pass limit so we can say and limit is equal to and then we can Define the max limit we can do it right here within the code set it to something like eight now if you save the file the form is nicely going going to put it in a new line and the last parameter that we need is and order is equal to popularity so now if we open up the terminal once again and go back to page and you can see tabs script is immediately saving us from some trouble later on it lets us know that it expected one argument but got zero an argument for page was not provided once again I know that some of you don't like using TP script 2 much but you can see how even in simpler apps it starts paying off because it lets you know that something is wrong so let's pass number one as the page that we are after let's save it and if you open it up you can see inv valid parameter page value one and limit 8 must be a number between one and this is 100,000 so let's see why that is happening it looks like I used a dollar sign right here instead of an end sign so we definitely want to fix that and now we're good and as you can see we get eight anime from the page one this is great we're getting some data so now instead of Simply consol logging that data we of course want to return it which is exactly what we are doing right here so going back to our page we can now remove this declaration of getting the fake data and we can indeed say cons data is equal to a weit fetch anime this time we're going to render the anime cards so if we go back and reload you can see that something is happening so let's fix it we can see that our page is rendering the anime card to which we're passing the index and it would be nice of us to define the type for this as well in this case number with that said we know we're passing the entire item to our anime card so if we move into it we can see where we're rendering the image in this case if you open up your ter terminal you can see that image has the original but this is only the end of the path we're still missing the entire start of the API meaning the domain name so to modify it we can make this a template string that starts with https colon shikimori do1 and then we can put this as the dynamic part of this template string and close it like so if we now save this and go back the images are back so now what we have done so far is we have received the first eight images this time from the real API but now is where the magic is going to happen we have to make this infinite loading work to render more anime cards as we scroll down now let's go where the magic happens and that is not the anime card not the homepage not even the server action but it is our component called load more Yep inside of this component we're going to load more pages as they come and yes I use the word page even though technically nowhere on the screen you can see numbers of pages but still the premise is the same we paginate normally as you usually would but this time as we scroll down we load a new page so the idea is still the same but it's how we approach it the differs so the primary difference here is instead of clicking the next button we're going to trigger the next page once we scroll down to a specific point of the screen in this case to the end of the screen and the question now is how are we going to know how far our user has scrolled thankfully there is a phenomenal mpm package that has over 1.3 million weekly downloads that does that for us the only thing we have to do is install it and then just use in view that's about it it's going to tell us once we reach a specific point so going back to our app we can open up our terminal without stopping this one I can press this icon here to open up another one side by side and then I can run mpm install react D intersection Das Observer this is a really lightweight package and it's only a helper to do what we need to do everything else you'll do on your own so now that we have it how do we use it well you can simply say import use in View and that's going to be coming from react intersection Observer how to use it well you just call it right here const it gives us a ref and it gives us an in viw property which is equal to use in view that's it now see how this starts with use which means that it is a hook so now if we were to save this file our app would broke and I knew that even before I clicked save why well that's because you cannot use hooks on the server side so that means that we have to convert our component to be a client side component by giving it a use client directive now our page works and still the entire page is server side rendered only this little button is rendered on the client side now we want to attach this ref to something we want to attach it to this div at the bottom by giving it a ref equal to ref so now it's going to know once we scroll to it so let's figure out how it works once the ref has reached something happens so let me demonstrate we're going to use the use effect hook right here which is usually getting run once something happens right so we can declare a typical callback function right here with a dependency array that's going to track the changes in the in viw variable and we of course have to import use effect coming from react which we can do right here at the top by saying import use effect coming from react great so now in here we can put a simple alert saying load more which is exactly what we want to do but there's one more thing we have to do we have to wrap this alert with the if in View Property so only if we are in view then we want to load more or in this case just alert that we do want to load more so now if we go here and if we slowly scroll down once we hit that scroll bar you're going to notice that we got an alert load more which makes it a perfect time to load the next page of our anime cards so how are we going to do it well right here we can call the same server action we have created before fetch anime coming from at slapp SL action we can call it and we need to pass a page number in this case it's going to be two right then we can use the do then to get a response we can call it res and then we want to update the data that we want to show which we can use the state for so here we can say use State and use that state snippet call it data and set data which is at the start going to be equal to an empty array and of course we have to import use State coming from react now once we get the response we can simply say set data and here's the thing we not only want to update the data but we want to keep track of all of the data we've had before so for that reason reason we want to return an array spread all of the existing data and then to it add all of the data from the response by spreading it by saying do do dot rest now tapescript is going to complain that we cannot add these elements to a simple array so let's define the type as well which we can do here by using this syntax and then say anime prop which we can import automatically from that/ anime card and say you want to get an array of anime props this way tab script knows exactly what it's getting while we're here we can also see that our linter is complaining that it's missing data as a prop so yes if the data changes we do want to recall this use effect so we can add it to the dependency array and now there's one point I want to make we are already fetching this data on the homepage you can see we're using the fetch anime and then we display it but in load more we want to display page two 3 4 and so on so to do that we can simply copy this entire section from the homepage and then paste it right here inside of this react fragment and then of course don't forget to import the anime card so this section is for all of the subsequent pages from page one okay let's now save it and let's check it out in the browser going back to the side we of course know that our first page is already here but as we scroll down let's see what happens oh you saw the new line appeared and then another new line which means eight new anime which is exactly equal to the second page but now as we scroll further you're going to start noticing that the images repeat so that's not quite good right to fix that we have to implement a new variable which is Page we have to keep track of the page we're currently on so let's declare it right here at the top of our component let page and we're going to start with a number two so what is the exact reason why we put it outside and not as a state here well you might have as well use the use State snippet and then just use the page and set page but in this case it's not even necessary we can have just a simple variable and update it as we normally would so here below the data once we get to the end we can actually increment the Page by one and here we can use the real page number so every time that we get into a new view we can show and fetch a new page so let's test it out back on our page I'm going to scroll down first second and then we have third fourth and so on so this is actually working but it seems like nothing is happening because it just loads instantly if I go a bit faster you can see loading but then that doesn't look so good which is the exact reason why we want to implement some animations so now would be the perfect time to do that to add animations to our Simple app we're going to use framer motion the most popular animation library for react and nextjs but there are many questions on how to use this with nextjs considering that everything is Serv side rendered and we want that how can we achieve these client side rendered animations how can we get the best of both worlds well that's exactly what I'm going to teach you right now so let's open up the terminal one more time and let's run mpm install framer Das motion the second and the last package we're going to use in this video now that we have it we can navigate over to our anime card because we want to apply that animation directly to each individual card but we have a couple of problems here in react doing that would be super simple but in nextjs due to the fact that we're using serers side rendering it gets a bit tougher let me explain why the way you would use framer motion would be simple you would just say import motion from framer motion and this exposes all the elements that you can use like divs images but they're animated so now if you want to turn this div into an animated div what you could do is just say motion. div and then you can provide it a couple of props they're going to make it all work so in this case those props are going to be as simple as saying variance is equal to variance and we can Define them right here at the top by saying const variance is equal to to Hidden opacity Z like this and visible opacity one so we want to shift it from zero to one we also want to give it the initial state which is going to be set to Hidden we want to give it the animate which is going to be visible so the only thing this is doing is it's going from opacity 0o to opacity 1 and then we can Define the transition by saying transition is equal to delay is going to be set to let's do 0.1 seconds or let's do one so it's really obvious we can also do ease which is going to be ease in out the way that the animation happens and then we can also add a duration which is going to be 0.5 seconds finally there is one additional thing that we can add which is called a view Port which in this case is going to be set to zero now if we save this and go back to application you can see that we get an error and this is something that I always like to point your attention to we are within a serers side component because we have never said use client but apparently something is trying to use context which is not going to work with a server rendered component and I'm going to turn this div into a new component which we're going to create so even though our app is not working right now let's fix it we can fix it by creating a new component right here called motion div. TSX inside of here we're going to import what made us switch the client side anyway so that's going to be import motion from framer motion and we know that for this we have to turn it into a client side component so we can say use client the only thing we're going to do here is we're going to export const motion div is equal to motion. div so now the only thing that is client side rendered is this specific div nothing else in this anime card so this parent element right here is going to be client side rendered and everything else is going to be children which are still going to be server side rendered so what we can do now is we can replace this with this motion div which we can import from that/ motion div and we can keep all of the other props the same and now if we go back the app again works the animations work as well but if you pay close attention there's no use client directive on top of the anime card just a little one right here where we export the functionality from framer motion now our animations are still not perfect and we can verify that by putting our browser side by side side to our code now if we reload the page you can notice that there's nothing and then they all appear at once this is not what we want to do so thankfully let's verify where are we calling the anime card from we're calling it in two places we're calling it from the homepage where we pass the index of the element we're loading and we're also calling it from load more where we're also passing the index of that specific card so we can do a little bit of a trick right here we can accept that index as props into our anime card and we can stagger the animations from every subsequent card first of all delay is going to be equal to index times and then a specific number for example 0.25 seconds so now to load the first card is going to take 0 seconds because the index is zero the second one is going to be 0.25 seconds next one is going to be 0 0.5 and you get the idea so now if we just reload you can see the first one loads and then all of the others follow this is great now you might think that this is working and it is but if you start scrolling really really far down you're going to notice that it's going to take so much time for these items to actually load now you can see they're loading but they're really really slow so there's a little thing that we can do to fix it that's because our St staggering element right here is applying to the entirety of the elements we're getting back so it's going to take more and more time to load them so what we can do is only apply the Stagger for that specific batch or that specific page of elements that come back in this case what we can do is go back to our action. TS and instead of it returning just the data it can return the components themselves so let's go to our home and let's copy this this entire data. map right here we can then go here and paste it return data. map anime card then you're going to notice that we have a lot of warnings and that's because we are in a TS file but since we're using some components we have to rename it to TSX right here and then we have to import the anime card from components anime card as well as the anime prop from components anime card great so now instead of just returning the data we're returning the presentation of that data as well so there's just two little things we'll have to do we'll have to go back to the page and we don't want to map over it two times now our data actually already is the content that we want to display so the only thing we have to do is fetch the data right here and then just dynamically render it because we're already mapping overhead and we have to repeat the same thing for our load more component if we go here we don't have to map over the data anymore we just have to render it because the data is already getting mapped over within our server Action Now typescript is complaining that it's no longer getting what it should get so what we can do is we can just modify the type by saying export type this time we're going to call it anime card is equal to jsx do element and now we can replace the anime prop with anime card and if we save it we're good the data is here I can close my code and I can expand my browser so we can admire it in its full Glory now I'm going to slowly scroll down we're going to see that the elements will indeed start getting animated I'm going to scroll a bit faster so we can admire all the animations as well there we go how cool is this everything is getting animated we can see new posts appear this is amazing but of course it's our code that makes it possible so if we go back I want to give you a quick recap of what we have done everything is happening right here within our action. TSX where we fetch the data and then we return it you can either return it just as data or in this case we're immediately returning it as a mapped over page and we can know that this is a server action because we have the use server directive on top now we're using this server action in two places we're using it right within our homepage which is bear with me another server page because it doesn't have the use client directive we just normally call it right here and it works like a charm then we can go to the other place where we're using it it's going to be within components load more and now check this out load more is a used client directive page meaning a client side rendered page and we still normally call this fetch anime the same server action we're calling in the same way within our server rendered page which means that we can call server actions both within client and server rendered Pages they're just so powerful finally you'll learn how to use this in View Property so once we scroll down we refetch the entire page and display it you learn that infinite scroll is nothing more than just going over the next page and next page whenever we go down it's like clicking the next button for you and you also learned how to use framer motion within serice side rendered Pages we have it right here the only thing you have to do is apply the use client directive here export that div and then all the children within that anime card are going to be server side rendered although only the motion div is client side a lot of exciting stuff and this has been kind of a simple application to Showcase all the power of what nextjs has to offer the creators of nextjs are often releasing these small apps to teach you different concepts and this is the example they've done for partial pre-rendering it is super quick and loads incredibly nicely if you would want me to do more of these Simple app apps but then focus more on explaining the concepts just let me know down in the description but of course this is just the beginning and that little infinite scroll that we had that you can see right here is just one example of phenomenal features that you need to have in almost all of your new modern next4 apps which is exactly why I created a much much larger project than this one I'm talking Dev overflow this one specifically has pation not infinite scroll but it has many other features you saw the loading there you see different layouts there's even login even a dedicated job search page and I cannot go without mentioning the ability to create your own stack Overflow questions count answers and Views have code blocks answers to those code blocks and then even the ability to generate an AI answer and yes you can learn all of this by enrolling into our ultimate next gs14 course which right now is on a crazy Black Friday sale but no matter when you're watching this video we always have Regional discounts turned on as well it is the best course right now that is completely up to date that can teach you everything you need to know about nextjs to use it like these companies do it's more than just using it like react you cannot use it like react you have to embrace all of the server side principles like we did today with server actions and more and then truly use it the way it's supposed to be used and just a note this entire application is built entirely on server actions so if you want to learn them in more depth this is the best way to do that and also learn how to make your app SEO optimized and performant the entire course has a lot of Deep dive lectures with special animations like this to better understand the concepts we have the build and deploy of the dev overflow and finally we have active lessons these are special lessons that test your knowledge where you have to develop a feature with our guidance so are you ready to get started just go to jm.pro next4 or click the link in the description I'll see you inside
Info
Channel: JavaScript Mastery
Views: 156,969
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, framer motion, tailwind css, next js, nextjs portfolio, react js, next 13, nextjs tutorial, portfolio website, react portfolio, framer motion animation, tailwind css portfolio, next14, next 14 tutorial, next 14 project, nextjs14, nextjs 14 project, nextjs 14 server actions, next js server actions, next js server side rendering, next js 14 full course
Id: FKZAXFjxlJI
Channel Id: undefined
Length: 42min 50sec (2570 seconds)
Published: Sat Nov 25 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.