
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
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 We are ready to dive into the community part of this application.
00:00:05 Here we can show the top users that ask questions or provide responses.
00:00:11 What would a social app be without some kind of a profiles interface?
00:00:15 In our dev overflow, that is called a community.
00:00:19 So let's first focus on creating an action that'll allow us to fetch all of those users.
00:00:25 We can do that by heading over into Lib.
00:00:28 actions, and we can define a new action file, which I'll call user.action.ts.
00:00:37 Within here, what is the first thing that we do?
00:00:40 You have to know this by this point.
00:00:43 It is the use server directive where we tell JavaScript and Next.js that we want to run this file on the server.
00:00:52 Here we'll create a new server action that will allow us to fetch all the users that have joined so far with pagination.
00:00:59 So as we always do, let's first head over into our types, global.d.ts.
00:01:05 And at the bottom, I'll create a type for our user by defining a new interface of user.
00:01:13 And in this case, you could totally make use of the iUserDoc that we created right before, allowing us to specify which properties each user has.
00:01:23 But we would need to pick only a few selective properties on the front-end side, because as a user just fetching other people's data,
00:01:30 we don't have access to all the info, only some of it.
00:01:34 So in this case, I'll actually create a new user interface that'll contain the data that other users can see.
00:01:40 So I'll add an underscore ID of string, a name of type string, a username of a type string, an email of a type string.
00:01:52 an optional bio of a type string, an optional image of a type string, an optional location of a type string, an optional portfolio of a type string,
00:02:06 and finally reputation, which will also be optional of a type number.
00:02:12 More on that soon.
00:02:13 And now we can head back right here and export a new asynchronous function called getUsers that'll accept params of a type paginated search params.
00:02:26 And it will return an action response.
00:02:31 Specifically, it'll contain users of type user array, and it'll also contain the isNext functionality of a type boolean,
00:02:42 as we always have with the paginated search params.
00:02:46 And we can close it right here and open up a function block.
00:02:50 Within the function, first things first, we check whether the validation is correct.
00:02:54 So I can check const validation result is equal to await and we call the generic action to which we can pass the params.
00:03:06 As well as the schema of paginated search params so that it looks something like this once prettier formats it.
00:03:13 Right below, as usual, we'll check if validation result is an instance of error.
00:03:22 And if it is, we'll simply return our error handler.
00:03:26 How simple it is.
00:03:27 Once you have already built it out, you just have to pass the validation result as error response into it.
00:03:33 And you can see why it makes sense to create these long reusable functions and handlers.
00:03:39 Because later on, you'll see yourself using them super often.
00:03:43 Once we make sure that there's no errors, we can destructure some data, such as the page, which by default we can set to one.
00:03:51 the page size, which by default we can set to 10, the query, and the filter.
00:03:56 And these will come from Params.
00:03:59 We also need to define the skip number.
00:04:03 This will make sure that our pagination works.
00:04:05 So we'll say cons skip is equal to, wrap it in a number parameter, page, and then minus one.
00:04:12 And once you wrap that in a pair of parentheses, you want to multiply it by page size.
00:04:19 That'll look something like this.
00:04:21 And we can also make the limit equal to page size.
00:04:25 This is the typical procedure of how you make your pagination work.
00:04:29 Next, we need to deal with sorts and filters.
00:04:32 I can do that by saying const filter query of a type filter query, specifically of a type user will be equal to an empty object for now.
00:04:46 And then if a query exists, we'll say filter query.
00:04:52 .$OR is equal to an array where we check either if a name or an email exists.
00:05:01 And we'll use a regular expression so people can search with case sensitive or case insensitive.
00:05:07 They can type John uppercase, lowercase, whatever they want.
00:05:11 And make sure to import this user from add forward slash database, as well as the filter query from Mongoose.
00:05:18 Now that we have the filters, we also need sorts.
00:05:21 So I'll say let sort criteria is equal to an empty object.
00:05:27 And then I'm going to open up a switch statement that's going to check for the filter.
00:05:31 And based off of the filter, like if it's newest maybe, we can change the sort criteria, and I have to change it, sort criteria,
00:05:41 to make it equal to an object of createdAt minus one, like this.
00:05:48 And then we break it.
00:05:50 I can duplicate this a few times.
00:05:52 Not newest, but rather oldest.
00:05:55 In that case, it'll be created at 1. Or maybe most popular, in which case, we can simply sort it by reputation of minus 1. And by default,
00:06:06 we can just do the same thing as newest, like this.
00:06:10 Now, we can open up a try and catch block.
00:06:14 In the cache, we can simply return handleError errorAsErrorResponse.
00:06:20 And in the try, we first need to count up all the documents to know how many there are.
00:06:25 So I'll say const totalUsers is equal to await.
00:06:30 user.countDocuments based on this filter query that we're using to query them.
00:06:37 Next, we can fetch the actual users by saying const users is equal to await user.find find all the users that match this query,
00:06:48 sort them by the sort criteria, skip a specific number to get to the specific page, and limit them to a specific limit per page.
00:06:57 Based off of all of this data, figure out if the next page exists.
00:07:01 So if isNext, then that is true, only if totalUsers is greater than skipPlus.
00:07:10 users.length.
00:07:13 Finally, we already know what we need to return because we specified it right here at the top, an array of users, as well as the isNext of boolean.
00:07:21 So let's return an object that will say success is set to true, data is set to users, is json.parse, json.stringify users,
00:07:34 and isNext.
00:07:36 I was just about to say that the function no longer complains, but wait, it does.
00:07:40 It says the return type of an async function must be a promise.
00:07:45 So what we need to do is actually wrap this action response in a promise.
00:07:51 We'll only get access to it once that promise has been resolved.
00:07:55 And now we have this get users server action.
00:07:58 So let's commit it, implement, get all users action, commit and sync.
00:08:05 And in the next lesson, we can display all of those users on the dedicated community page.