
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code for this lesson is available at
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 Similar to filters, we need pagination on all the different pages, including homepage, community, collection, later on also jobs,
00:00:12 tags, tag details, and even a pagination for the answers within each individual question.
00:00:18 So to create it, let's create a new component within the components folder.
00:00:23 And let's call it pagination.tsx.
00:00:26 Within it, you can run RAFCE.
00:00:29 And to see how it's working while we're developing it, let's import it into our homepage.
00:00:35 So that is the root page, and we can put it somewhere near the bottom, below the data renderer.
00:00:41 So I'll put it right here, self-closing pagination component.
00:00:47 So now if we go back to the homepage, at the bottom you'll see pagination.
00:00:52 And what I'll do is I will set the page size to default to 2. That way we don't have to create hundreds of different posts to be able to move between different pages.
00:01:04 We'll have one post per page, but that'll still allow us to test the full pagination functionalities.
00:01:10 So just set the page size to 2. Next, let's develop the pagination component by heading into it, and let's accept all the props that we're going to later
00:01:19 on pass.
00:01:20 Of course, the most important one is the page.
00:01:23 If not passed, we can default it to one.
00:01:26 The isNext property, which we're returning from every single server action.
00:01:31 Now we'll finally put it to use.
00:01:33 And a container classes in case we want to modify how the pagination component looks, depending on where it's being called.
00:01:41 And this will be of a type props, which we can define right here.
00:01:46 Interface props.
00:01:49 That accepts a page, which is either a number or an undefined or a string is next, which will be a boolean.
00:01:58 And then the container classes, which is optional of a type string.
00:02:03 Now we can wrap everything in a div and that div will have a class name equal to.
00:02:10 I'll make it a CN class name so we can define some base class names like flex, w-full, items-center, justify-center, and a gap of two.
00:02:23 And I'll also pass in the container classes to it as a prop.
00:02:28 So now pagination text disappeared, but now we'll add something else within it.
00:02:34 We have to add the buttons that'll allow us to go to the previous page as well as to the next page.
00:02:40 We can do that by opening up a dynamic block of code and checking if the number version of a page is greater than 1, that must mean that we can go back,
00:02:52 that there should be a previous button.
00:02:54 So let's create a button.
00:02:56 It'll be a Schatzian button component coming from that slash UI forward slash button.
00:03:01 And to it, we can pass a p tag that'll say prev as in previous.
00:03:06 For now, let me give it a class name equal to light dash border dash two, btn flex, min dash h dash 36 pixels.
00:03:19 items-center, justify-center, gap of 2, and a border.
00:03:26 And then I'll also style this p tag by giving it a class name of body-medium, text-dark 200, light 800. And we cannot see it yet.
00:03:38 That's because the page, I think, is equal to one right now.
00:03:41 So if I check if page is equal to one, then we can see this Prev button we created.
00:03:46 But okay, for now, since we only have one page, not more than one page, let's actually hide this.
00:03:52 Next, below this button, we can show a div that'll have a class name of flex-items-center, justify-center, rounded-md, bg-primary of 500, padding-x of 3.5,
00:04:09 and padding-y of 2. Within it, we can display the current page.
00:04:15 So I'll do a p tag and I'll give it a class name equal to body-semi-bold and text-light 900. And simply, I'll render a page right within it.
00:04:30 So now we can see the work currently on the first page.
00:04:33 Now, similarly to the previous button, which I can add a comment for right here, say, previous page button, I will duplicate it below the div and then
00:04:45 I'll say, next page button.
00:04:48 We're going to show the next page button only if the isNext property is true.
00:04:54 So if isNext, which we're calculating on the server side, then show the next page button.
00:05:00 I'll make it say next and the rest of the things for now can be the same.
00:05:05 Of course, neither the previous nor the next are being shown right now.
00:05:09 Once we do decide to show these buttons, we'll have to give them some kind of an onclick.
00:05:13 So let's give both of them the same onClick, which is going to be equal to a callback function that calls the handle navigation function.
00:05:22 But to the first one, we can pass the option of prev and to the next one, we can pass the option of next.
00:05:29 And now we can define that function right above by saying const handleNavigation which will be equal to a function that accepts a type of the navigation
00:05:42 we want to do and it can either be equal to prev or Next, like this.
00:05:48 Within it, we want to figure out if there is a next page, what is that next page?
00:05:53 So I can say const nextPageNumber is equal to, if type is equal to previous, then we want to make the next page number equal to the current number minus one.
00:06:08 else we'll make it equal to the current number plus one.
00:06:12 Now not always will that be possible because if we're on page zero, then we cannot go back, right?
00:06:19 So I'm going to say const value is equal to if next page number is greater than one, then I'll return the next page number dot to string Else,
00:06:31 I'll return null because it's not possible to go to that page.
00:06:36 And once we have it, we can form a new URL.
00:06:39 So we need to update the URL by saying const new URL is equal to form URL query, which is a utility function we created.
00:06:50 to which we can pass the params equal to searchParams.toString.
00:06:56 And pagination will be a client rendered function.
00:06:59 So at the top, we have to give it a useClient directive because we're going to use state.
00:07:04 And then at the top, we can get access to the searchParams by saying const searchParams is equal to useSearchParams coming from next navigation.
00:07:15 And we also want to get access to the router.
00:07:18 which will be equal to use router, also coming from next navigation.
00:07:23 So now that we're getting these values right here, we can get access to the right search params with a lowercase s.
00:07:30 And we also have to pass over a key, which we want to update, in this case, the page, and then the value that we want to set to this page.
00:07:39 Of course, the value coming from here.
00:07:42 But keep in mind, this value has to be a string.
00:07:44 Null is not assignable to string.
00:07:46 So if we have nothing, let's just make it equal to an empty string.
00:07:50 This gives us the new updated URL.
00:07:52 So if everything goes right, let's push to it by saying router.push new URL.
00:07:58 Great.
00:07:59 So now in the homepage, which is right here, page root.
00:08:04 We have to pass the right props to the pagination component.
00:08:08 First, the page, and then the isNext property.
00:08:11 This isNext is coming right here from the data of the getQuestions.
00:08:15 If you pay close attention to the server action, you'll see that in the return, we're passing over the data.
00:08:22 And as part of the data, we have the questions as well as the isNext functionality.
00:08:27 So we can destructure it right here, isNext, and we can pass that data over to the pagination.
00:08:34 I'll say page is equal to page and isNext is equal to either isNext or false.
00:08:42 If we don't have access to the isNext function or boolean in this case.
00:08:46 So now we can test the pagination by reloading on localhost 3000. And if this was working right, we should only be able to see one post,
00:08:55 but we see two.
00:08:56 And we can test this by adding another question.
00:08:59 So say, ask a question.
00:09:01 I'll add something like pagination?
00:09:05 And then I'll say, how can I implement the best pagination there is?
00:09:12 I'll add the tags of JavaScript and React.
00:09:16 You know what?
00:09:17 I'll add Next.js as well, because implementing pagination in Next.js is much different than implementing it in React.
00:09:24 In Next.js, you can make use of the search params, like what we are doing, to make it easier and more efficient.
00:09:30 So let me ask this question.
00:09:33 There we go, no answers found.
00:09:35 Now, if I go back to the homepage, check this out.
00:09:39 We have two questions here, and then there's this some kind of a button.
00:09:42 Right now, it doesn't look that good, so maybe we have to provide an additional class name.
00:09:47 Yep, that'll be text-dark 200, light 800. There we go, now it says next and I'll also pass this over to the PREV button.
00:09:56 And for the time being, I'll also give it a margin top of something like five to divide it a bit from the posts.
00:10:03 So now, if you click the next page, check this out, we actually go to page number two and there's a previous button allowing us to go back and the next
00:10:12 button is hidden because the server action returning the questions figured out that there is no next page.
00:10:18 So it returned false for the isNext variable.
00:10:22 And if I go to previous, previous now disappeared, as you can see, but also the page number disappeared.
00:10:28 That's a bit weird.
00:10:29 Let's see, on which page are we on?
00:10:31 Oh, we set page as an empty string right here.
00:10:34 That should not be the case.
00:10:36 So what if I set it to null instead?
00:10:41 And save it.
00:10:41 Now, if I clean up my URL, go to next and then go to previous.
00:10:48 Oh no, it's still the same thing because page is set to nothing.
00:10:51 Maybe in this case, the value can be the next page number itself to string like this.
00:10:58 So if I comment this out and clean up my URL bar right here.
00:11:05 We are on the page 1. If I click Next, we go to the page 2, and you can see that updates properly right here.
00:11:12 Now, if I click Previous again, it'll just make the value of the page 1. And we don't need this check right here for the value,
00:11:20 because we cannot click to go Previous anymore, because we have this check right here.
00:11:25 If number is greater than 1, only then show the Previous button.
00:11:29 So there is no way we can go to page 0. And there we go.
00:11:34 Now we can go next, you can go previous, and you can dynamically change the page size if you want.
00:11:41 So if we now go back to the homepage, we can bring back the page size to 10. And if you do that, it'll just say the page number right here,
00:11:48 and the previous and next pages will be completely hidden because they're not needed.
00:11:53 Pretty cool, right?
00:11:54 You just implemented the pagination.
00:11:57 The only thing we needed are the numbers, a div or a p tag that's going to show the actual page, and then the functionality to modify the URL bar,
00:12:07 similar to what we did with the filters.
00:12:09 The rest of the stuff was done by our server actions that we have created before.
00:12:13 Pretty cool stuff, right?
00:12:15 I know I keep repeating myself, but this app really is using the best practices, and I'm so happy that I prepared it so I can share them with you.
00:12:22 Now, for some practice, let's go ahead and copy this pagination.
00:12:27 And let's implement it on a couple of other pages.
00:12:30 First, I'll head over to our collection page, where we have our saved questions.
00:12:37 On there, we currently have just the two questions.
00:12:40 So maybe I can set the page size by default to one.
00:12:43 So only one post appears per page, just so we can test it out.
00:12:46 And then at the bottom, right here, below the data renderer, we can render the pagination.
00:12:53 Oh, let's get access to the is next coming from data.
00:12:58 And we're passing everything to it.
00:13:00 One post on one page and one post on another.
00:13:03 And we can go back and forth between those two pages.
00:13:06 I'll bring this back to 10. And there you have it.
00:13:09 Pagination is implemented on another page in a super simple way.
00:13:13 We can do the same exact thing with the community page.
00:13:18 So if we head over here, just to show you how it works, I'll change the page size to 2. And below the data renderer, I will add the pagination right here.
00:13:28 And we'll get the isNext from where we're fetching the data.
00:13:31 If we do this and head over to the community page, you'll see we get two.
00:13:37 And on another page, we get another.
00:13:40 Pagination is working great.
00:13:43 Of course, I'll bring the page size to 10, so we see some more users once they come.
00:13:47 Now, let's implement the pagination for the Question Details page.
00:13:51 We can do that by heading into the All Answers component, because we want to paginate the answers.
00:13:58 But to paginate the answers, we first need to head over to the Question Details, which is Question ID page.
00:14:05 We can also set the page size to 2, just to be able to test it.
00:14:09 And then, to the All Answers component where we're rendering them, we can now also pass the page which will be equal to the number version of the page
00:14:21 or one by default.
00:14:23 So let's head into the all answers and let's accept it as a prop.
00:14:29 So first things first, I'll get the page right here and I'll add it right here at the top.
00:14:34 Page is a number, as well as isNext is going to be a boolean.
00:14:40 So let's define it like so.
00:14:42 Oh, I might need to pass that isNext as well.
00:14:45 So I'll say isNext is equal to, and we get it from answer result, question mark dot isNext, or by default, we'll set it to false.
00:14:56 So now in the all answers, we can accept the isNext prop next to the page.
00:15:03 And we can put both of them to use in the way we're already used to.
00:15:08 It is as simple as rendering the pagination right here below the data renderer, pagination as a self-closing component imported from dot dot slash pagination
00:15:18 to which we can pass the page equal to page.
00:15:21 And isNext equal to isNext.
00:15:24 And if you save it, right at the bottom, we have access to our pagination.
00:15:28 Oh, but we weren't checking it out for the community, but rather for the question details.
00:15:33 So if I head over to a question that has a lot of answers, more than two in this case, right now we can see just two.
00:15:42 And then there's a page to load the next answer.
00:15:45 If you click it, we see this third answer, or we can go back to see the previous two.
00:15:50 Of course, this looks even better on desktop, where you can literally see that there are two answers right now, but we don't want to load all of them at once,
00:15:58 so we can also see just the third one.
00:16:01 This is working beautifully well.
00:16:05 Now we also have to do it for the tags, but before, let's just bring back the number of answers to 10 by default.
00:16:11 And I'll go to the tags page.
00:16:15 I won't even test it by lowering the number of tags right here.
00:16:19 I'll just get the isNext from the data coming alongside the tags, and I will render the pagination component to which I'll pass the page,
00:16:28 the isNext property, and I'll say or false by default.
00:16:33 And if we head over to tags, we see one.
00:16:36 You know what?
00:16:36 Let me test it just to be sure.
00:16:38 I'll say, give me four tags by default.
00:16:40 We have four and we have one more.
00:16:43 So this is working incredibly well on tags as well.
00:16:47 And finally, we also have the pagination for the tag details page.
00:16:52 So once you go to a specific tag, you want to be able to paginate through the questions that have something to do with that tag.
00:16:59 So to implement it on there, I'll just copy this pagination, head over into tags ID.
00:17:06 page, so that is this one right here.
00:17:10 And below data renderer, I will render the pagination, pass over the isNext and the page, and the isNext is coming straight from the data.
00:17:20 So now you can see the pagination here as well.
00:17:23 And just like that, in a single lesson, we have not only implemented the pagination, but we have successfully added it for every single page that we have
00:17:34 developed on this application throughout the entire course.
00:17:38 Give yourself a big pat on the back because now we have filters as well as pagination on all the pages.
00:17:45 Great work.