Dynamic Catch-all Routes in NextJs 14

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so let's see what we're talking about today we're talking about Dynamic routes Dynamic catch all routes and dynamic optional catch all routes in nextjs and we're going to learn about them through the docs the concepts and also by creating this application here where I have a users table and all of which is just rendered from one page or one Dynamic catch all segment where we can click on different users each user has a a list of to-dos so if you're fetching the to-dos and if you click on the to-dos you also see the details now if you look at the URL structure up there we have the for/ users so that's when we land in for/ users if we go to a specific user we would have users for slash1 this shows this a specific user and a list of to-dos and if I click on a specific to-do we even go deeper by having for slash to-dos for SL1 which is the IDE of that specific to-do where we would just see this details here so let's go to the documentation start from scratch and then we're going to jump into the code and build that application or this example together so Dynamic routes are useful when you don't know the exact segment names ahead of time and want to create routes from Dynamic data so you can have blog posts that are sitting inside your CMS or inside a different git repository and instead of having static routes for every blog post or every slug you want to create a dynamic page that receives this slug receives this ID whether it's a blog post or a product and then fetches that specific blog post and renders them all so instead of creating a 100 different pages you create one Dynamic page that can receive that ID and render different products or different block posts now the convention is to wrap the folder's name in square brackets you probably know this already so for example square bracket ID or scroll bracket Slug and this is going to be the name of that specific property in the prams object we're going to see in this example here now Dynamic segments are passed as prams to layout Pages routes and generate metadata function so this object is passed by nextjs to your component functions so that you can have access to this Dynamic segment to actually fet the corresponding data so as an example here we have the blog and then Slug and a page JS which is responsible for rendering that Dynamic page where this slock is a dynamic segment of the blog post so our page component receives this prams object as a prop and inside of it has this a slog property it's because we named it slog if we name it ID will be ID and then here we would just fetch the necessary data from our database and then render it here this example they're just showing this lock so with this structure you can have examples like for/ block for/ a b and c they're all going to be captured with the same Dynamic segment and the prams object would would look like this uh with a slug property and then the actual value as a string now before we talk about Dynamic catch all routes let's talk about generate static prams this function that you can export from your pages now because this Dynamic segments are Dynamic meaning that they're not known ahead of time if you don't export this generate static prams function these pages are going to be rendered dynamically and by rendered dynamically I mean on demand at request time because we don't have the specific values at built time we're going to have to look at the URL at request time on demand and generate these Pages if you want to gener these Pages a statically there should be a way for us to tell nextjs all the possible segments that our application has so therefore nextjs can generate them statically ahead of time at build time and then serve them up when a request comes in if you're coming from the pages router or nexts 12 there was a function called get static paths that you had to export together with uh get static props which would instruct nextjs for what segments or paths specifically generate these Pages a statically and that has been replaced with this function called generate static prams in the app router and there is a subtle difference between the two functions or the way that they work that I'm going to explain but basically you would export this generate static prams from your page the same place where you were accessing this Dynamic data to render your pages and then here you have to return an array of objects and each object is going to have a property named the same as whatever you named this Dynamic segment so in this case Slug and then the slug is going to contain the possible values for this slug or the segments so for example here we're getting all of the posts inside of our application we're mapping over all the posts and for each one we just r ing an object or returning an object that sets the slck to post. slock and with this function now next J knows all the possible segments or values for these Dynamic segments ahead of the time so at build time is going to go ahead and generate all these Pages EST statically and serve them up quickly rather than rendering them or generating them on demand at request time now there's two differences between the way that this works and the get static paths inside the pages router the first one is well this just Returns the slug whereas in the pages router or inside the get static path you had to export an object that has a prams property and then the prams property was an object and inside that object you had a slug so it's just simpler and the second difference which is more important is inside the dynamic segments in the pages router the way that we used to do nextjs you had to export the generate static paths otherwise your application would error out but here this generate static prams is optional so it's for optimization if you want these pages to be rendered statically at build time you can export it but if you eliminate it the function component for the page is going to run anyways on demand at request time and the page is going to be created the difference is that here is going to be rendered dynamically at request time but if you export this function it will be generated statically so you don't have to it's optional if you want to optimize for static Pages you can so have that in mind we're going to use that also inside our application and becomes a little bit more trickier when your slug is actually catch all which we're going to learn about now which is not a simple string it is actually an array of strings so let's uh look at the catch all segment now Dynamic segments can be extended to catch all subsequent segments by adding an ellipsis inside the bracket so you can add these three dot dot dots and this is going to capture everything that comes after so all the subsequent segments as well for example if you have the shop and then dot dot dot slug as a dynamic segment it will match for/ drop for/ cloths but it also matches for/ cloes for/ Toops or even another segment so it catches all of them hence the name catch all segment so for example this same path that we have here can have this example URLs shop a shop forab and ABC but there's luck in these cases when you're dealing with catch all routes is going to be an array of strings it won't be a string like the example before it will be an array of strings so we're going to also see this in action in the code and the last one is optional catch all where you have the dot dot dot but instead of one square bracket you actually wrap it with the folder name with two square brackets okay so for example this one is going to match for/ shop and optional means or the only difference is between the catchall and the optional catch all is that the optional catch all also matches when there is no segment um subsequent to the first one so it matches for/ shop and for/ Shop for/ clothes and anything that comes after whereas here this one which is coming after shop there has to be something thing so it it is for/ a a a and C so it catches the subsequent ones but the optional one says hey this Dynamic segment it's catchall but it's also optional so also render this same page for for/ shop and this is what we're going to use inside our application and in this case as an example your page is going to match for SL shop or for / a Ab and ABC and in this case your prams object would be an empty object if there is no slug pass because it's optional you won't have any slug present and if you do it's going to be an array of strings because you're still inside of this dot dot dot or catch all type of route down here we see um the typescript types that you can pass in depending on your structure so if your structure is like so your slug is a string if you're using a catchall route your slug is going to be an array of string if it is optional well you add an optional and if you have two segments one after the other you just have to set that type depending on your specific structure there's not one size fits all formula here it's just you have to see what is your route or folder structure now with this out of the way let's jump into the code and actually put all of this in action so I've started from a brand new application that I've actually cloned from this repo it's called Next shat CN it's a starter template that uses nextjs typescript tell me CSS and chat CN built in you can click this use this template create a new repository out of this and then clone it in your local machine and start working with it what it gives you is this header up top it comes with the theming like light and dark theme and then a simple footer um some plugins for tnd to sort your utility classes in a nice way so we have this uh next TS starter so if you go to the repositories here you can see this next TS which is also a template for um typescript nextjs but this shaten one actually comes with chaten so if you are into using chaten um you can use this to start from the same starting point that I have so let's look at our app structure inside the layout let me close this off from a high level as I mentioned I have the theme provider this is from the next themes package to enable us to have the light and dark theme I have a simple header and a simple footer inside the header what I'm doing is rendering the home and the link for the users page and a theme toggle that is this button here that allows us to toggle the theme pretty straightforward so so let's go close this off and go to our page component this is our homepage so on the homepage if you're not saying anything it's just Dynamic routes and then the fun begins where we wanted to actually go to for/ user so when we click here on for/ users you're actually going inside of this folder let me just make this a bit bigger so inside of users I have this Dynamic catch optional catch all route for slug inside of it there is a page and also there is a layout so let's go to the layout and see what we're doing inside the layout and then we dive into the page so inside of the layout I have the users layout so this is the page that we seeing here you can accomplish this in different ways this is one way of implementing this optional catch all route where we have the same layout and the same page rendering the users the specific user page and also the to-dos page and I thought it's a good opportunity to also see this structures together or actually use a layout here but you can also implement this in different ways so in the user layout we receive the prams this is the prams object that next year sends to us layouts would receive a children these are the pages or nested layouts that can be plugged in here and what we're doing here is rendering this kind of structure down here where we are mapping over our users for each one we are showing showing this links on the right hand side and then underneath I'm just plugging this children but because this is a flex it just uh whatever children we pass as a page here it will be shown to the right hand side um where my mouse is right now so inside of this layout I'm actually calling this get users function to fetch all of my users to then map and create this table here now let's dive in to get users real quick so I've created this lib folder where I have different types for my to-dos for my users and I have this utils this comes from chat CN for merging tail and classes and then I have this users where I have defined some functions that allows me to talk to my database in this case I'm using uh mock API I've shown this before so it allows you to have Mock apis and call your endpoints to get some resources in this case users and to-dos um once you create account it gives you an endpoint you can create resources and then shape the schema for each of these resources and then hit the endpoints but this is the same place that you can talk to your database fish whatever data that you want from your CMS um from your Shopify whatever that maybe so I'm getting the users in this instance and I'm returning an object with the users or error if an error happens so inside the layout I'm getting all the users and I'm mapping to create this shell over here so let's close this off go back to our page now so inside of my page this is the actual page inside of the dynamic slug or dynamic catch all route I'm still receiving the prems again I'm getting this slug out if I don't have any Slug it means because I'm optional couch all route this also matches for slash users and that's what's happening here so I'm hitting the for/ users and this page still catches this because it's optional because I have double square brackets and I'm saying if there is no slug well we are on the all users page so just render this users component which just says select a user to see the list of toos this is this thing rendering here and again this page this component is rendered inside this page and this page is plugged into our layout because it's passed to it as the children and it's plugged in here rendered in a display Flex so it just shows up on this side going back inside of our page if I do have a slug this means that I am on a specific user page so I have another component it's called user let's just dive into that and I'm passing this lug to it and this is responsible for rendering a specific user so what am I doing here well first I'm receiving this slck that was passed to me and then I'm getting the first segment of my slug that's the user ID so if I click on this specific eye it's user users and then for slash so the first segment of my slug which is at index zero is going to be the user ID this is that specific user now the next slog is going to be the string to-dos so if I click on one of these to-dos you can see I have users the user ID then I have the string to-dos and then the to-do ID so that's why I'm skipping here the first segment was the user ID the second segment is going to be the string to-do and the third segment here is going to be the to-do ID so what are we doing with these data well I'm getting the user idid and I'm passing it to this get user by ID function to get the user so let's dive into this real quick it just hits the same endpoint in our mock API and then we pass in an ID to our user's endpoint to get that specific user so we get this specific user if there is no user or if there's any error I'm calling the not found function this is going to just show the not found page or your four four page if you don't have not found page next I am also passing this user ID to get to-dos by user ID that's another function that's going to hit the users's ID and then to-dos this is going to give me all the to-dos for this specific user so I'm getting all the to-dos sure that's the to-dos I'm also trying to see if they are on a specific to-do detail Page by finding the to-dos by mapping over these to-dos and then finding the one that matches the to-do ID this to-do ID that we got out of this lock now it may seem a bit confusing but if I go on the user and do not click on any of these to-dos well I have the user and then the user ID so this user ID is there but there is no other segment so there is no to-do ID so I understand that I'm not on a specific to-do page so this to-do would return undefined because this to do ID doesn't exist but I have the user so I show the user I still fetch the user and down here what I'm doing is show the user data their image their email and I'm mapping over the to-dos that I fetched down here by passing that same user ID I'm mapping over the to-dos for each one I'm showing you a link that if they click on they can see a detail but if they click on it they would go to user user ID todos and that too ID once they click on any of these to-dos by going to that route they're going to end up on this same component again because this is a catchall route it catches all the subsequent segments so it is get caught in here again but this time around this to-do ID would have a value because now we have seted this to-do ID to this segment so therefore when we're mapping over to to-dos to find this a specific ID or the one that matches here this to-do would actually be an object and down down here I'm saying if there is a to-do or if we are on a to-do specific page or if that segment actually exists will then show the detail of that and that happens when I click on it I go to for/ to4 SL1 that ID is now present in the URL it gets captured by the same page I find a specific to-do and render the details down here I can click on different ones to show different details or click on a different user to see different to-dos and then click on different to-dos now to show the active to-do just like how I'm underlining here inside of this link inside of the class I'm just looking to see when I'm mapping over my to-dos if the to-do ID is the same as the to-do ID that I got out of my slug here this means I'm on that current to-do so that's the active to-do and if it is deactive to-do I'm just showing this underline decoration sky that shows this blue underline I'm also doing something similar in this users list so if you go back to the layout where we are rendering this shell of our users inside of this links when I'm mapping over each user if the user ID is equal to the user ID that it is present in this log or in the segments of our URL that means that specific user is is active so therefore I'm showing this underlines this is responding to whatever ID is up there so it just reads that compares this with this ID and draws a line similar to here now we could have had this layout also inside of the users's folder so right now the layout is inside this Dynamic catch all route it could have been inside the user but the only difference would be that if the layout was inside of the users which is one level higher than our Dynamic segment we wouldn't have gotten this prams object inside of our layout so I moved it inside the dynamic catchall route specifically to just render the active user so that I get the specific prams because if this was outside we could still fetch all of the users this is still not specific to any user so we could get all of the users render the shell I only moved it inside so I have access to this prams object because now this layout is inside of the dynamic catell out which then allows me to get the user ID the specific ID that's present in the URL and compare it to the list of my users and actually know which of my users is active and that's all there is to it to render all of these pages and different sections or segments with this one page and one layout now before we wrap up I want to talk about the generate static prams function now to show you what I mean inside of our page we are not exporting the generate static prams so right now all of our Dynamic segments are going to be rendered dynamically which means on demand at request time now to show this in action let's actually stop the dev server and build our application so if you look closely for this users and then our Dynamic catch all route you see this Lambda sign which down here it just tells you that it is dynamic it's server rendered on demand using node.js because we haven't specified any runtime it just runs or it's deployed as serverless functions but our point is that it is going to be on demand it's Dynamic it's not static okay so let's contrast this with actually exporting a generate static pram function from this file so let's bring in our generate static prams I'm going to explain what we're doing here so we're getting all of our users that's the same function we've seen before if we don't have any users we just return and empty array it's is saying he don't generate anything statically generate everything on demand now for each user that I have inside of my users that I got back if they exist I'm going to map over them and for each one I'm going to fetch the to-dos for that specific user and if the user doesn't have any to-dos the only thing I push to my slugs array is an array that contains the user ID that's the first segment inside of our URL which is this 4/7 or for/ whatever comes as the first segment after the for/ users and if I do have some toos for this specific user for each one I'm pushing this array to my slugs which contains the user ID and then the to-do string and then the to-do specific ID so therefore for each to-do I'm returning one specific array so if a user has multiple to-dos there's going to be multiple of these arrays where I have the user ID the same the to-do is a string and then the to-do ID changes and if a user doesn't have any to do the only thing that we're pushing is the user ID now these are still arrays we have to turn them into an object that has a slug property that's set to this array so at the end for generating all the paths or all the segments that I want nextjs to generate statically at build time I'm going to map over my slug array that I pushed different sorts of arrays and slugs to and for each slug I'm going to return an object that has a slug property set to that specific array that was pushed to my slugs array and I'm returning this paths and with this now nextjs knows what segments it can generate statically at build time so let's save this up and open up our Dev terminal again and run the pmpm build again here we go and if we look at our Dynamic catch all route here it's no longer marked with the Lambda which was representing Dynamic on demand rendering instead it's this field dot which is SSG or static site generation which is a static HTML and if you look closely here it also gives you the examples or some of the paths that was generated so for/ users for SL1 to and one and down here it also says plus 37 more paths so it mapped over every user and for each one fetch the to-dos if it had it generated the arrays of different segments to pass into our slugs so when a request comes in for any of these pages instead of generating this page on demand it just serves up the static version that was generated at buil time and that's wrap for this video folks we talked about Dynamic routes and dynamic segments in nextjs we talked about the convention of wrapping the folder name with the square brackets we also talked about catchall routes and also optional catchall routes that is going to allow you to match any subsequent segments inside the URL as well and the difference between the catch all and optional was that the optional also matches the index when you don't have any uh Dynamic segments whereas the catchall at least needed one Dynamic segment we also talked about the generate static prams function function that is going to instruct nextjs to build some of these Dynamic paths or dynamic segments statically at build time versus rendering them dynamically on demand we also talked about the difference between generate static prams in the app router and they generate or get static paths inside the pages router where we had it before and it was required but here it's optional it's more an optimization technique if you don't export this function you can still have Dynamic segments and dynamic pages but all of them are going to be rendered dynamically on demand at request time and if you do export the generate static prams and give nextjs specific paths to generate you don't have to generate all the possible paths in this case if we did get all the users and all the to-dos but if you have a humongous database of users maybe you don't want to create this for all the users or blog posts for that matter Maybe you just want to statically generate your popular blog posts based on their previous views or previous engagement so you don't have to return all the possible paths whatever you want to return or whatever you return from this function is going to be statically generated at build time and the rest are still going to be rendered but dynamically on demand if you have any questions hit me up in the comments like always and I'll see the next one bye-bye
Info
Channel: Hamed Bahram
Views: 14,716
Rating: undefined out of 5
Keywords:
Id: 2qkAfddVbKM
Channel Id: undefined
Length: 28min 24sec (1704 seconds)
Published: Tue Apr 09 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.