Production-Grade Next.js

Server Side Data Fetching

Scott Moss

Scott Moss

Superfilter AI
Production-Grade Next.js

Check out a free preview of the full Production-Grade Next.js course

The "Server Side Data Fetching" Lesson is part of the full, Production-Grade Next.js course featured in this preview video. Here's what you'd learn in this lesson:

Scott live codes CRUD helper methods to avoid raw database queries and instead use the database created in getServerSideProps. The functions used to get, create, and update folders and docs are covered in this segment.


Transcript from the "Server Side Data Fetching" Lesson

>> Doesn't really matter what database you use, SQL, MySQL, Postgres, whatever, it's mostly going to be the same. You just got to look at the specific example of how to cache a database connection for your database. Some databases do have support like I know SQL has MySQL Server lists, and stuff like that.

And I know depending on where you're deploying, if you're on AWS they have, I think, Aurora is like a serverless SQL now. I know they have SQL services now. So it really just depends on where you're deploying is how you're going to get some of this stuff. This is how we're gonna do it on verso and locally, so, all right.

So we're good with the connection here, pretty simple. The other thing to take note is that it's done for you, but if we go look at the middleware, we can look at some of the stuff that's already here. So you can see we have a middleware here that basically connects to the database using that connection function that we made.

And it just attaches the database of the request object and the client to the request object. So that means any functions that we go create, which we will in a minute, we can access the database via request.database if we use this middleware, which was very helpful. Because we need the database to actually do things, same thing in other places, so yeah.

Pretty cool here. Now, if we don't have any questions, we can move on to doing some server side data fetching. So so far we've been doing data fetching server side, but it's been at build time. So with git static props, not real data fetching server side at runtime, but git server side props.

And we're not gonna hit our API one time to do it. Yeah, so let's see how that's gonna work. What we're gonna do is we're going to first, we need to create some crud helper methods that basically abstract the database away from us so we don't have to use raw database queries everywhere.

We're gonna just use these functions that do it for us. The reason we want to do that is because we're actually about to use the database that we just created inside of our server side props in the pages that we want to actually query for data. So for us, we want to query data on this page because we want to get the folders, we wanna get some folders here.

So in order to do that, we need to add the logic to query the database in the server side props function of this page, okay? So that's basically what we need to do. In order to do that, first, like I said, we're going to create some distractions around that, we're going to create some helper methods.

So what we're going to do is if you go into the DB folder, you'll see a file for like folder.ts, and doc.ts. This is where we're going to fill these functions out. And there's a user one too, we're going to fill them out and have them do something.

So we'll go do that one. And these aren't that difficult, they're pretty straightforward. Even if you don't know Mongo, it won't be that difficult. So we'll go to db, and we'll go to, let's hit the folder one first. So it looks like we have a createFolder, and then we have a getFolders.

So if we actually want to create a folder in Mongo, the way that works is, we can say folder, or newFolder equals then we got the DB here, and we can say db.collection. And we're gonna get the folders collection. And we're gonna say insert one. So we're gonna insert one, and we're gonna give it an ID, and we're gonna use this thing I have, we're gonna call it NanoId like that.

And then I'm also gonna say a folder has, so right now we don't have any schema, so you might be asking like, where's he coming up with this stuff? We don't have any schemas, we didn't make any. I usually use Mongoose for schemas, but MongoDB actually supports schemas now.

I just didn't make any, because I just wanted to not focus on how to write schema for a database. We're just going to focus on how to do next.js stuff. But you can do schemas for a database with MongoDB if you want to, as well. It's pretty intuitive.

Anyway, we're gonna keep going, so I'm gonna say a folder has an ID. If I don't put a ID here, it's gonna default to an object ID, so it's totally fine. I don't like using object IDs if I don't have to, converting from an object to an ID all the time.

It's so annoying all the time. I don't like doing it. So if I get the chance to just not do it, I'm not gonna do it. So I'm just using this thing to generate an ID for us. So we got that. The next thing I want to do I know folders have, I basically just wanna pass this in.

So this folder object right here, pretty much has everything that we need. So I'm just gonna do that. Like that. So now we got a folder. But I believe, so for one, we want to weight this, this is async. I believe the way this works is there is an operation here.

So it's like an operation. So when you do an insert with the raw Mongo SDK instead of returning you the document that you just inserted, it will return you an object about the operation, how successful it was, how many things got inserted. And then on there, you'll get access to the actual, the thing that you want.

So in this case, we got ops, and what I wanna do is I just wanna return ops(0), which will be the actual thing that I inserted. So then I can just return newFolder, like that. So that's creating a new folder. Getting a new folder, or getting folders, it's much easier I can just say return Db.collection folders.

.find. And I wanna find all the folders who has a created by of this user ID, then I'm gonna say toArray, like that. And that's it. That's how you get folders, very simple. It won't hurt to add it I guess. It's nice to have a t create it that field, I guess, I'm not actually using it.

I don't think I'm actually using to create it at anywhere in the app, but I'll be consistent. If you do add it though, one problem that I ran into with next.js in server side props and static props, is that if you try to return a prop, that object inside of a prop, and one of those fields is a date object, it'll break.

It won't let you do it. It will say it couldn't serialize it. And there's a good reason why. So that's why you see me adding a date, I'm converting it to a string because if it's a real date object, when it gets to next.js it will break on the server side.

So remember, if you have date objects that you're trying to pass to next.js as props, it won't have it. You need to serialize them first, change them first. So that's what I'm doing here. All right, the next thing we want to do is for the docs, this one is a little more involved.

So if we want to get one doc, we can say return db.collection for our docs. And I want to find just one by an ID of whatever that ID is, like that. That's it, super simple. I get doc's by folder, very similar to that one. So I'm sorry, this should be find one, there we go.

This one would also be find one and this will be for, this is find me, I'm sorry. So we will find here and then we'll say folder, and it'll be folder Id, like that, and then two. All right, and I think I got a typo somewhere. Yeah, right there.

There we go. So we're gonna get the docs by the folderId toArray, this is gonna give us a list of them. And the createDoc is very similar to what we do before, so this will be New doc, this will just be, wait, db.collection folders.insertOne, like that. There we get ID of a nano ID here that I have.

And then I want to just pass in the doc, that's passed in like that. So it's got a created by, it's got a folder, a name, and an optional content. And then the last thing I want to do is I'll do the same thing I had before with the creator app, like that.

We should be good. And then I'll get the operation ops. And then obviously return it. Like that. So now we got a new doc. And then the last one is gonna be to update one document. So this is a little more involved, cuz we have to update it and then we gotta query it again.

Because the update doesn't actually return the updated document, we have to query it again. So, we'll say awaits db.collection docs.updateOne by the id of id. And we want to dollar set, this is how you update in Mongo. By doing set, you're saying, I only want to update these fields, don't replace all the other fields.

This is just update the fields that I'm giving you. And I just wanna set whatever updates were passed in. That's gonna be an object. And I can await that. So that's good. And then what I'll do is, I'll go ahead and get the doc by saying await db.collection docs .findOne.

And you get an id here of id. And return to doc. There we go. So those are basically just our CRUD helper functions that we're gonna use. Pretty much all of these, we're going to use these and most of them inside of the app service side props. That's going to be a big function, it's gonna do a lot, intentionally.

So it's gonna do a lot of stuff there. The last one that we're not actually using but I can go over, is just a get user by ID. But I think you might get it at this point. We're just going to return db.collection users .findOne, id and then id, that's it.

That's how you get the user by ID.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now