Mastering Modern Next.js Data Fetching: Tips, Tricks, and Best Practices

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
data fetching in next.js let's cover the three primary ways to fetch data server fetching server fetching with a library client fetching some best practices here as well as an example here towards yet and yes my styling here is a beautiful but the point of this video is data fetching and also I'm feeling a little bit under the weather here so I'm just making this audio only and then of course I'm doing this screen share here but let me know in the comments below do you do you like when I just do audio only like this like I know some people find it less distracting if there's not like a video of me because of my striking good looks but just let me know in the comments below what you think about that so with that I've created this application here and I will push this code up to GitHub and if it's not in the description below let me know because I just forgot to do that so what we're going to do here is go through and a lot of this information most of it comes from the next JS docs on auto perform data fetching in your applications and the docs basically go over and also their docs change fairly regularly so it could be different from now but I I think the the concepts of this video will all remain so like I said there are three primary ways to fetch data in xjs you can do it on the server on the server using third-party libraries or on the client using third-party libraries and technically speaking there's more ways that you can do it you wouldn't necessarily need to use libraries but next yes recommends these three ways so let's first go over server fetching and we're going to just kind of cover conceptual review for these first few and then get into a actual example here in a sec but for Server fetching here you can use Fetch with async weigh-in server components route handlers and in server actions so here this is just a snippet that I got from the next JS docs you're showing an example of this Joe egg add example of this I clearly I can't talk when I'm feeling a little under the weather either but here they just have an async function get data and this is just JavaScript here guys this is nothing that's really nexjs specific so they have an async function gudeta and they Define this within a server component here so index.js a component in your application is going to be a server component unless you explicitly say that it is a client component using a string at the top of the file saying use client but since this doesn't do this it is a server component and with the server component here there are basically just making a fetch request using the fetch method so next JS extends the browser's fetch method here so you can use the fetch method they await the response they check if it's not a okay response here and they throw an error if it's not because they feel the fetch data else they return their response.json and then here down below within their page component it's an async component and they await their git data call so not none of this if you're familiar with JavaScript this should look very straightforward to you um you can just use fetch within your server components and it basically works as as you would expect here Now by default next.js caches The Returned values from fetch in a server data cache and you can read on next.js docs a little bit more if you're interested in how exactly the server data cache works I don't think it was uh particularly relevant for this video but if you want me to cover that in future videos we can but they say that they do this so that data can be fetched at build or request time cached and reused on each request so hashing effectively will allow you to like if you try to make the same request to go get the same data well you don't necessarily want to have to go and make a request to a server and have that Network latency on every single request like if you could just store that data in a cache and serve it more immediately rather than making a network Quest that would be great and that's effectively what next.js does my default here is caching the return values from your fetch method so in this example up here when they do this example fetch to api.example.com if they make another fetch to this exact same URL to get the exact same data next.js is just going to return the cache response so it doesn't have to make another HTTP request to go get this data which improves performance the less Network requests that you can get away with probably the better here and as I say here caching data is great and all but you know you have to make sure that your cash is up to date so like if the data at this URL changes well you don't want to return that date anymore you want to make sure to revalidate that data and validate that that is the correct data at this point in time and the way that you can do that in next.js is twofold so you can use a time-based way of revalidation or you can do an on-demand way of revalidation and to perform time-based revalidation you can do the following so here's another snippet from the next JS docs here in which you do this at a timed interval you can use the next revalidate option of the fetch method to set the cache lifetime of a resource in seconds so here in this fetch method here they have the URL but then as the second argument to the fetch method they pass in an object in this object you can pass a next property in that next property can also point to an object so they have this next property here and they point to this object and this object can contain a reality property in which you set a number to the property which is going to represent the amount of seconds that you want to revalidate your data at this given URL so what this is basically saying here is that okay we're going to fetch data at this URL here but every 3600 seconds I don't try to do public math but I think that is I think that would be like 60 times six so I think that would be once an hour is what they're trying to re-evalidate this data and great they actually say right out here rivaldi at most every hour so they revalidate this data every hour so they're saying okay if you make this request again at this URL within the next hour we're just going to return the cached response but if it's outside of an hour then we're going to validate that the data is the same else we're just going to return the new data since it's outside of an hour here and if you don't want to revalidate by like path name here so this is every time you fetch to this certain path you're going to revalidate it every 3600 seconds if you want to revalidate based on Route segment so to revalidate all fetch requests in a route segment you can use the sigma config option so within a layout.js or page.js you can export a constant called revalidate and then you can set that to a number of how many seconds that you want to revalidate so revalidate at most every hour is what this will be saying if we export cons revalidate and set that equal to 3600 here all right so this is time based revalidation making sure to read already on a certain interval but you can also revalidate on demand here and you can do this by path or by cash tag inside a route Handler or a server action so to do this by hashtag you can add a tag within your fetch request so here in this similar examples I showed you earlier they fetch a certain URL and then there's a second argument to the fetch method they pass an object with a next property in the next property also points to an object and this object has a tags property and they pass in an array with a string called collection so they're giving this URL a tag of collection and then down here you can import revalidate tag from next forward slash cache and within this route Handler here this is a route Handler that they Define in their app here they can basically get the tag from the search frames of the URL and they can pass that into a revalidate tag and this will perform on-demand revalidation so they can revalidate when this route Handler is handling this request here so you can add a tag like so and then pass that tag into revalidate tag in your route handlers by using request.nexturl.searchbrains.get tag and I would say if you find yourself in the use case of needing to do on-demand revalidation I would definitely you know just consult the docs just know that you you can do it and I have a rough understanding of how you do it and you know you don't need to memorize all this off the top of your head I would just you know if I was implementing this in our professional application I just you know I've read the dog so I know that you can do automated validation then I'll just search next.js on demand revalidation and you can work through the docs to figure out exactly how to do it here but you can also do on-demand revalidation by Route so the way that you can do this is you can import reality path again from next forward slash cat cache but then instead of passing this tag into the revalidate tag function you can actually pass the path in to the reality tag function so using request.nexturl.searchprains.get and passing in a string of path that's going to return the path or this request here in this route Handler you can then pass that path into the revalidate path function and that is going to do on-demand revalidation for this path okay so it's going to revalidate the cache there to make sure that data is what it should be okay so it gives you revalidate tag here from next forward slash cache and it gives you revalidate path from next forward slash cache and it allows you to revalidate an entire URL path or just revalidate apps that have a certain tag that you can use within your fetch request here all right and then with that if an error is thrown while attempting to revalidate data the last successfully and generated data will continue to be served from the cache you can opt out of caching by when you call the fetch method here you can pass in your url but then as a secondary object you can pass in a property called Cash and then set that to a string no hyphen store so that's basically saying for this URL I do not want you to do the default behavior of caching this request now alternatively you can also set a revalid property to zero or if neither of those sound good to you you can also export a constant Dynamic is equal to Auto within a page.js or layout.js file so similarly to what they do right up here export cost reality equals 3600 within layout.js or page.js you can export a constant called Dynamic and set that to the string Auto so this would read export const Dynamic equals Auto and you export that from a layout or page.js and that will make sure that you do not cache for that route segment so that is server fetching that was like the meat of doing your requests in xjs and we'll we'll cover that in uh in a second with best practices but you can also server Fetch with a library on the back end so if you use external libraries to make requests in your server components and it doesn't use the fetch method or doesn't expose the fetch method you can configure caching and revalidating behavior of those requests using the route segment config option and reacts cache function so if you're not using the fetch method on the back end and you're using some library that does its kind of own thing and it doesn't expose that then you are gonna probably have to manually do the caching and revalidation so you're not going to get it necessarily just out of the box with next.js so they're going to say that whether the data is cash or not will depend on whether the route segment is statically or dynamically rendered data can be revalidated on demand Bypass or by hashtag inside rawhandverse or server action so here's an example of how you would kind of manually add caching if you're doing server fetching with a library that doesn't use the fetch method so you can import cache from react and then you can set how often you want to revalidate this data So within kind of this this function here you can export a constant revalidate and set that equal to the number of seconds that you want to revalidate this cache and then this might look a little bit complex here and this is written in typescript so they have types in here but all you need to do is wrap this cache function imported from react you wrap that around your async function to make your requests and that is going to allow you to do your caching so in this example they wrap this cache function around their async function here that gets an item from their database and it's automatically going to Cache this and they're exporting the console screen validate to revalidate this data every 3600 seconds and then for Klein fetching not a ton on this page but I just wanted to kind of show you that next.js recommends using SWR or act query if you need to fetch data on the client these libraries allow you to handle caching and revaliding I think the the makers of nexjs also created SWR I've used that in the past and I really like it but I've also heard really good things about react query as well so those are good options for fetching data on the client but as nexjs recommends here in their best practices whenever possible fetch data on the server so the reasons that you might do this is because it'll allow you to have direct access to the server keep sensitive data Under Wraps Fetch and render data in the same environment reducing back and forth between the client and the server so on and so forth so fetching data on the server I really like that you can just directly access the server you don't necessarily need like a API layer of your application that you is like the middleman between your database and the client and then you can also since you're not shipping your data to the client you can keep some more sensitive data under apps a little bit better and reduce some back and forth between client and server so fetch indeed on the server probably a good idea and they also recommend a fetch data where it's needed because fetch requests are automatically duplicated so if you have a fetch request in a certain component within your next JS component hierarchy but you also want to use that data in a different component that is maybe across several branches in your next JS hierarchy that is totally fine just fetch that data where it's needed you don't need to worry about you know just making one fetch request in a parent component and then passing that data down your next.js or react hierarchy you can make those fetch requests kind of co-located within those components because if next.js sees you making the same request in two separate components it's going to de-duplicate those requests and it's just going to make one request okay so it's not going to make both of these requests at the same time and I'll have some redundancies in your application it's automatically going to de-duplicate them so it's going to allow you to just make these fetch requests wherever you need the data to kind of co-locate your etch request alongside your components that use that data rather than needing to make one request at like the top of your hierarchy and then pass that down your component tree and then just getting kind of messy with things alright so it it will automatically de-duplicate the same requests so just fetch data where you need it and then also it recommends using suspense and streaming when needed for components I have an entire video showing an example on loading and streaming just you know search loading and streaming within my next.js playlist and you can find that and I go into much more detail with that but the tldr is at and you can basically wrap a suspense component around certain components that might take a long time to render and that will allow you to render that basically separately compared to like your entire page so instead of needing to wait for that long rendering component to finish loading to render out your entire page you could render out your entire page and then just show like a little loading indicator or maybe a little skeleton component for that single individual component that is rendering within the page check out the entire video but you can wrap things into suspense to kind of progressively render your components so you're not just showing a blank loading page the entire time the user can actually start to interact with your page while maybe a component that is a little bit heavier kind of loads into your page and then finally here they recommend to be aware of parallel versus sequential data fetching so I'm going to show you a example of this because I I think this is one that's super easy to mess up and can lead to just slow application so in this example here they're showing you how to make your fetch request in parallel so they have an async function right here called get artists and or get artist singular and it just makes a fetch request to this certain endpoint and it Returns the response but then they also have this fetch request get artist albums and it makes a fetch request uh this endpoint and it Returns the response now within their page what they're doing is they are calling the get artist function as well as the get artist albums function but they're not awaiting these requests so they're not doing artist data equals await get artist and albums data equals a weight git artist albums instead they're just returning a promise to artist data here is Wallace to alwin's data and then they are calling await promise.all and passing in their artist data promises as well as their albums data promise and then they are using that within their page here and what this is allowing them to do is it's preventing them from needing to like if they awaited and get artists here then they wouldn't be able to make this get artist albums request until the get artist request has a result because they are gonna wait for it right in this line here so that creates a waterfall so it would make this get artist albums request dependent on this gay artist request so they would happen one after another they would happen sequentially but rather if you don't await these and you instead await I'm gonna stop all passing in an array of promises or these two promises here that allows you to make these requests at the same time and just use this data when it returns rather than doing a sequential waterfall which I'll show you in our example here okay so be aware of parallel versus sequential data fetching all right but now let's go to this example here so in this example I have this beautiful page but let's actually look at my code Editor to see what's going on here so here's my code editor I'm just using vs code here and I'm in my example page.jsx here okay so you can see within my app folder I'm in my example folder and I am in my page.jsx file within my example folder but all I'm doing here is I have a very similar example here to what they have in their example in my best practices page so very similar to this I'm doing this here in which I have a get post function in which I'm just making a request to a Json placeholder API it's just like a unlock data API that gives you some data for testing or if you're creating YouTube videos and stuff like that and I'm just returning the data some data from this API so I'm making my e-sync request right here and then I'm also doing a get albums function call which I'm hitting this API forward slash album and I'm returning this data here so I have two separate fetch requests and in my component here my example page I have my two fetch requests right here in which I call get post as well as get albums but as I just mentioned in kind of that parallel versus sequential data fetching you can see that I'm awaiting get post right here and then I'm waiting get albums within this function so if I look at my terminal here and then I go back to my create next app I go to my examples page and I refresh here to make those calls again I can see within my terminal that I make my jsonplaceholders.typecode.com and also quick note since this is a server component here I'm not using use client here at the top it's a server component it's going to show me these requests occurring within my terminal within node.js because I'm I'm making these server side okay so it's not going to be in my browser console because I'm making these as server requests but you can see here within this output it shows me making a request to placeholder forward slash posts but then it showed me that once this request finishes I then make this request to forward slash albums here so you can see this waterfall of I'm making this request to posts and then I'm making this request to albums and that is because I am awaiting get post here then I'm waiting get albums so get albums it can't be called until I'm done awaiting get posts so I'm making these sequentially here which is a bit of a a No-No so the way that we can fix this is I can change this and I can not await these anymore and then I can say const and I'm going to say data comma albums and I'm going to change this right here to data promise and albums promise and I'm going to set const data in albums is equal to promise and I need to await this a weeds promise.all I'm gonna pass in an array of my data promise as well as my album's promise so instead of needing to finish this get post function call and then making this get albums function call I make them both at the same time right here and then I just await the data with a promise.all and if I go back here I refresh my page quick and then I open my terminal you now see that I make these at the same time here I don't have that waterfall as it shows here so I make four slash posts as well as four slash albums I make these get requests at the same exact time rather than what we had earlier I was making this get post and then you can see it kind of goes into one level and it waits for that to be done and then it does get albums so this this kind of graphic that it shows here within my terminal is a very good example of how I make this request then this request but in this example I make these in parallel and if a network request say say that it takes you know some time to complete and maybe you're on a slow Network and it takes several hundred milliseconds then that could really really slow down your application if you have several data requests here and you're making them all sequentially and you're making one request after another after another after another and just imagine if we were doing like get posts here we are waiting it and then we're doing get albums and awaiting it and then we had like several more requests here I would take forever you would you would not want to do that instead it's a better idea to not await your initial calls here and then use promised at all to allow them to finish and then use the data thereafter okay so that is a big piece of advice there when it comes to doing these that requests within your application here okay so when you're making your server requests it's really pretty straightforward here as you can see um but hopefully this gives you an idea of making your fetch requests within next year so just to kind of briefly overview this again with server fetching you can use async away and the fetch method within your server components route handlers and server actions but you do have to be careful with that cache so you can set a revalidate property within your fetch request or you can export a constant call revalidate within your layout.js or page.js to revalidate on a segment level rather than on a route level like what it would do if you're using the fetch request and then you can also do on-demand revalidation either by setting certain tags within your fetchupless and then calling revalidate tag or you can just use a revalidate path and revalidate all the revalidate path function passing in your path and if you want to opt out of caching you can set a cache within your fetch request to no store or revalidate to xero or you can export a constant called Dynamic and set that to Auto within your page or layout JS and then with server fetching with a library you might need to implement caching more manually by implementing the cache function from react and then wrapping your async function that you get your data with with your cache function and then for client fetching it's a good idea to use either SWR or react query and then for Best Practices whenever possible fetch date on the server fetch data where it's needed because it automatically will be deduplicated you won't make duplicate requests use suspense and streaming when needed for certain components and also be aware of parallel versus sequential data fetching so I hope you enjoyed this I hope you learned a ton about making your requests and doing your fetching in next.js and I will see you in that next one
Info
Channel: Code Ryan
Views: 2,456
Rating: undefined out of 5
Keywords: coding, programming, frontend engineering, code, software engineer
Id: udOD6yAhjB4
Channel Id: undefined
Length: 29min 18sec (1758 seconds)
Published: Wed Sep 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.