Nextjs TypeORM TailwindCSS TypeScript Reddit Clone #22 Infinite Loading

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
yo class welcome back so right now in our app we are loading all of the posts in the home page and showing them uh right now it's okay because we only have about 20 posts but obviously this is not ideal because we could have thousands of posts and we don't want to fetch them all at once and show them so we could introduce some sort of pagination we could do pages and show page 1 to whatever but this is not the 90s anymore let's do something more modern which is like infinite scrolling which happens to be what reddit does as well so this goes to as an extra point to cloning reddit let's go back to vs code and let's open post.ts the routes file and here at the top of the get post handler i'm going to add two new variables so the first one will be called current page and this is exactly that we could have a default value for this or we could also take it from the query strings that are provided in the request so i'm going to give this a type of number and i'm going to give this a value so i'm going to say here between parentheses request.query because it's in the query strings dot page and by the way we need to bring back this request because we need it now and here i'm going say or zero so if this does not exist if it's undefined it's uh gonna default back to zero i'm gonna say as number to cast it to number and because it could read this as a string even though it's actually given as a number and i'm gonna duplicate this i'm going to create another one which we might neces might not necessarily use but you could use in different implementations i'm going to call this posts per page and this will represent the number of items that we will have per page so if we look at our app we have roughly let's see we have one through we have around eight in our site right so i'm going to set this to have the value that we get from request.query.count or it's going to be 8 by default so now we're going to paginate it's simple so inside of this post.find we're going to say skip so that it skips a number of items oops let me fix this and the number of items will be current page times posts per page because if we're in page 3 you want to skip let's say 2 times 8 which is 16 and then get the rest from that point but here we also want to say take posts per page we want to take the exact amount of posts per page so an example if page is zero it's gonna skip zero times eight so it's not gonna skip anything and it's gonna take post per page which is eight so it's gonna take the first eight and then if it's one it's going to skip eight and then take eight and so on so we are now done on the server side let's go to our index.tsx on the client side where we have the post on the home page and here first thing i wanna do is i wanna implement the mechanism that allows us to detect that the user has scrolled to the bottom of the page by the way do you see we already have only uh eight posts here which is pretty cool obviously we need to make it so that it loads more as we scroll down so we're gonna use something called intersection api which is a simple way for us to detect whether a div is inside or out of sight or we are scrolling into it or out out of it so the idea is that we need to track let's say in this example here this bottom post here and when we get to the bottom of it right here we want to load more and then as we load more we want to track the new bottom one and then when we reach the bottom of that one we need to load more posts so let's set this up so first thing i want to do is here in the homepage where we get the posts we are fetching the posts and then we are looping through them and creating these postcards and we want to track the bottom one so there's multiple ways of tracking it i'm going to track it with a good old id so let's open the postcard component and here at the top where we have this div i'm just going to add an id to it an id and that id will just be the identifier because that's unique so save that let's go back to postcard or to index.tsx so here first thing i want to create a state variable so let's use use state use state and this will be i'll call it observed post this will start as an empty string and let's import use state from oops not this shortcut you state from react and this will keep track of the current observed post so now i'm going to use use effect so use effect and here what i want to do is initially i want to check first of all if posts is uh is falsy so if there are no posts or so or post.length equals zero if there are no posts or we have no posts at all then we're just going to return because we're not going to track any post otherwise we're going to say const id and now we need to get the id of the bottom post which is posts so we're going to access post posts dot length minus one which gives us access to the uh last one and we're gonna say dot identifier and now we're gonna do a check we're gonna say if id does not equal observed post so if this is a new one then we're gonna actually uh track this one now we don't have the tracking mechanism yet we're gonna simply say set observed post to this new one because it has changed and here for the array of dependencies we're gonna add posts because every time post change changes we want to run this again so i'm going to create another function here so const observe element i call it observe element because you can use this to observe anything not just a post div so here this takes an element of type html element and it does something so i'm going to do a first check because sometimes you get an element and then you get the id of it but it might not have been rendered on the dom yet so i'm going to do a safety check say if not element so if it's undefined or null at the beginning we're just going to return otherwise we're going to say const observer equals new intersection observer and this is from the intersection api and this takes two things a callback which has entries entries and you could think of entries uh points on the div itself but we're just gonna track one point so we're gonna say if entries zero dot is intersecting equals true then do what we need to do at the end of the intersection when this happens so actually let's console log something and we're going to say reached bottom oops bottom of post and we're also going to say observer and this is why i put it in a variable because we need to access it dot on observe element and we haven't started observing it we need to say observer dot observer dot observe and we pass it that element this is slightly confusing because this is inside of there but it's simple we just create an observer and don't worry about this this only happens when the intersection happens and we say observer.observe we observe that element which is the bottom post and then the callback to when the bottom of the intersection point or the bottom intersection point is uh intersecting with the the edge of our viewport it's going to call this and it's going to console log and it's going to unobserve that element because we don't need to track it again because if we do then every time we reach any of these bottom ones it's going to actually trigger this fetching more posts if this is a bit confusing don't worry it was confusing for me the first time as well it's not a very intuitive thing to work with after entries i forgot to add some options and for options we're just going to say threshold and we're going to give one and this basically is a value from zero to one zero is the top and one is the bottom so we just need to do one because we need to track the bomb now we need to call this observed element and we're going to call it here when when the observed post changes so we're going to say observe element and we're going to observe document document dot get element by id and we're gonna observe this uh id that has changed and it's better not to use observed uh post here because it might not have changed yet so let's see if this is working so save so i'm just gonna refresh open the dev tools on the console and so if we scroll down there we go we reached bottom of post and this is the post that we're tracking in right now so now we need to when we reach the bottom of post we need to fetch more posts so swr has a really cool helper to do that and if we scroll down in the documentation you go to infinite loading you see there is this use swr infinite hook that allows us to do exactly that so here they show this example where you have this you put a git repo a package and then it loads you issues for that package and puts kind of the titles of them here and as you click load more here it loads more and for our example instead of clicking a button it actually triggers when we reach the bottom of the page which we already implemented so we just need to implement the rest of this so i'm actually just going to copy this from here at this use infinite scrolling or swr infinite call and paste it here and let's import this from swr and let's replace this so we need to fetch slash posts which just slash post here and let's say question mark and say page equals now the page is actually given to us here which is the size that starts with zero so i'm actually going to give this a name of page and this set size give it a name of set page so that it kind of makes more sense in our code and then give this page right here and remove the rest of this string and just delete that and we don't need to give it a fetcher because we already set up a default one in the object up tsx so remove that and actually i made a mistake this should be the index this should be the index that is given here the page is used uh somewhere else now this data that we get here actually contains an array of our data so if we give this uh right here if we give this a type of post array like we have up here it's if you hover over the data you'll see that it's post array array so we need to get the first element of that post or whatever elements are in there so they already give us a cool way of doing that here so here we say const issues equals that i'm actually gonna grab these two as well so copy that and paste them here actually makes more sense to paste them after so here instead of issues we're gonna say posts and this will if we have data we're gonna concatenate it with an empty array otherwise it's an empty array and let's comment this out because we're not going to use this anymore so here we're going to have our posts and also there's this loading boolean that we can use to change the state of our ui and we can give this a type of post array so this alone if we save it should still do the same and fetch the first eight but the only difference is now we need to trigger so for example here where they use the button so right here uh where is that button yeah so this button load more just sets the size to actually not this one this is the initial load uh where is it yeah this one so this one when you click it it sets the size to size plus one which is just the page just increments the page in our case so for us it's not the button like i said it's the uh reaching the bottom of the post so that will be inside of here where we reach the bottom we're just gonna say set page to page plus one now save this and if we go back to our app we refresh let's look at the network tab we see xhr so here we have a request to page equals 0 where we get our initial 8 posts and now if we scroll down there we go you see the bar became smaller and for some reason i don't see the other request here okay let me check again so i'm just going to refresh okay page equals zero we scroll down there we go we get we request page equals one and we have more and now the next one should be around here yeah we reached the bottom of it we request request page equals two which gives us i think a couple of more a couple more like uh yeah three more and if we scroll now down we don't request anymore because as we request page equals three we get an empty array and this is not tracked anymore so there's nothing tracked we know that we have reached the bottom so our code knows because if this id right where are we yeah right here if this id does not change we don't track any new posts we know that we already fetched the bottom fetch the latest posts actually one thing that i almost forgot is we could use this as loading initial data to show a piece of text that says loading similar to the piece of tech actually i'm going to get the exact same styling from the sub page where we show uh when there's no posts that should be around here yeah this text lg i'm just going to copy this text lg text center so we could go actually i think we don't even need this is loading initial data because this is kind of like unreliable because beyond the first load it's not going to be true at all so what i'm going to do i'm just going to get rid of it because we already have is validating which is true whenever we're fetching data which is exactly what we need so we could go right where are we yeah so these are the posts right so i want to show here at the top loading when we are initially loading so we're going to say if actually i forgot to put is validating at the start so if is validating and we put to this so of course instead of saying no post submitted we're going to say loading dot dot and then what we could do to differentiate between the first load and the preceding or the ones that come after we could just say if is validating and post dot actually we need to put an end and posts dot length oops length is bigger than zero then we show uh loading more let's say so save that and now if we go back if we refresh we briefly get loading for like a fraction of a second and if we scroll down i know for a fact we do get loading more but we don't see it because of how fast it loads them but it is the anyway uh one other thing i noticed is that the vote buttons are broken on uh on the actual post cards as opposed to the ones on the actual post page they're not broken they're working because we didn't update the logic there so obviously when we're not logged in we want them to redirect to the login page and when we're logged in we want them to work properly so first thing is let's go to the postcard so actually here we need to get authenticated so right here at the top we can say const the structure authenticated from use auth state and then scroll down actually don't scroll down just here in the vote function we're going to say if not authenticated then router which reminds me we need router so let's say const router equals use router and make sure to import that from next so here if not authenticated router dot push slash login and also yeah okay let's say let's test this so obviously if we upvote there we go we go to the login let me login johns136 and here yeah it's broken here because it's not revalidating the data so a simple solution to this would be uh here in the use where are we use infinite swr or swr infinite we can get revalidate here as well and then we can pass it to the posts so here for each postcard we can pass a revalidate equals oops equals revalidate and we need to add this as a prop so let's go to postcard and here add revalidate we valid date and that's optional because you might not get get it from other places and this is of type function and here where we vote we're gonna check actually after we send the vote and it's successful we're gonna say if we validate oops revalidate then call revalidate did i misspell it why is it hard to spell revalidate let me check re-valid date oh okay i forgot to destructure it from the props okay so here added to the destructor props and also one other thing that we need to update about the logic here is that when we have the same vote as we did before so we're going to say if vote equals uservote and then set the value actually not vote value and set the value to zero all right save this actually save the index as well and refresh no i'm refreshing i need to get rid of that habit okay so another unfunny post if we vote the same that should cool it does revalidate and it removes the vote and then here as well the only thing we could yeah we could do something about detecting when the initial data has been loaded so that when it revalidates we don't get to see the loading again i think this is a a problem that is specific to the uh use swr infinite because with the other ones i don't see it happening so yeah all right that's it for this one please do make sure to like this video if you learned something or even if you were entertained by my silly humor or whatever and of course dislike it if you disliked it but please do let me know in the comment section what you disliked about it and of course if you haven't subscribed yet what are you doing come on subscribe and to the class and become the 10x developer that you always wanted to be alright so that's it for this one thanks for watching i will catch you in the next one cheers
Info
Channel: Classsed
Views: 1,174
Rating: 5 out of 5
Keywords: nextjs typescript tutorial, full stack typescript, nextjs typeorm, full stack nextjs, typeorm react tutorial
Id: p7KlyHoYyYY
Channel Id: undefined
Length: 18min 7sec (1087 seconds)
Published: Mon Jan 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.