Introduction to Next.js 13+, v3

Server Components

Scott Moss

Scott Moss

Superfilter AI
Introduction to Next.js 13+, v3

Check out a free preview of the full Introduction to Next.js 13+, v3 course

The "Server Components" Lesson is part of the full, Introduction to Next.js 13+, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Scott demonstrates the process of fetching data in server components using async and await. This segment also addresses a student's question about techniques to handle the latency of making multiple API calls to obtain data.


Transcript from the "Server Components" Lesson

>> All right, now we get to talk about fetching data and server components and client components. All right, let's get to it. So we talked about server components. As refresher server components are components that run on the server. They literally execute in a Node environment, which means you can do Node things.

The other thing though, that you might have thought about, and maybe you didn't know how this worked. But because they only execute on a server and they're not in like React's context of change detection and virtual DOM and all that stuff, they don't opt into the same behavior as a regular React component.

So you might be asking, so what is a regular React component? Okay, let me ask you this, I'm just gonna write a component. You don't have to follow along here if you don't want to, but I'm just going to make a new folder on the root. Our components, and actually, we probably will have this folder, so you can follow along if you want to.

But the code I'm about to write is not gonna be something we're gonna use. But let's say I have this and I have, I don't know, some Card component or something like that, right? Right, and then the Card component has some state, Some state, some updateState thing, Right, it has all this.

And then somewhere down the line, you end up calling updateState, right? You call this somewhere, right? What, do you know what happens when you update a state from a state hook in a React component? What happens to that component? Anybody want to guess? Or why do we even need hooks in the first place?

What is that?
>> To render it again with updated data.
>> Yeah, yeah, exactly. When you called that updateState function, it does render the component again with updated data. But what does it mean to render again? Right, if you really think about it, this looks like a regular JavaScript function, but one, you never call this function, right?

React calls the function for you, so that's one thing. And you have no control over when it gets called because it's parent might rerender which causes this to rerender, right? You don't really get that much control. Yeah, you can use things like memo and stuff like that to prevent it from rerendering, but that's because this isn't just like an ordinary JavaScript function.

You ever tried to put async in front of this and see what happens? You can't async await anywhere inside of here, right? That's because this entire function it needs to return, synchronously needs to return some type of JSX, right? You cannot block that rendering process, you will get an error.

So how do you do things that are async? Well, that's where hooks come along. So if you need to do anything that's async, if you need to remember something, because if this is a function, I mean, just forget about React right now. Don't even think about React. If I just had a function that did this, count and it took a number, let's just say num = 0 and then it said num ++, if I called count three times, what would it be num?

If I called count three times.
>> Pure JavaScript.
>> Yeah, pure JavaScript.
>> Four, right?
>> You would think so, no, it's just gonna be one cuz it's never keeping track of anything, right? Every time I call this function, this line runs what sets num to one, so I guess it'll be two.

So it sets num to one and then it increment it by one, so num is always gonna be two. So it'll be two here, iIt'll be two here, and it'll be two here, because I'm just resetting, I'm just running my function over and over and over again, right?

So to opt out of that behavior, in the case of React, where I wanna like, wait, hold on, keep track of this, hold on. When you call count again, I want to remember what it was before. So in order to do that, you have to tell React that you're interested in keeping track of this thing, and that's where hooks come in.

So that's because React is gonna just call your function, and it's just gonna just initialize it. So, you have to tell React, hey, I'm interested in keeping track of this thing. And React's like, cool, yeah, you could tell me that. Just make sure you use this hook, and you can tell me that by using this function that I give you, right?

If you give me this function, or I'm sorry, if you call this function that I give you, this function right here, that's you telling React that, yeah, change that thing that I told you to keep track of. And React's like, cool, here's that thing you told me to keep track of, right?

So this is a long way of saying with server components, none of this matters, you can just forget about it. This is just regular React, that's how client components work. Server components don't, they're just regular functions, they're really just regular functions that return HTML that just use JSX at this point.

So because of that, when it comes to something like data fetching or something like that, we can do whatever we would normally do to fetch data in a normal function, which is really cool. So, let's talk about that. So for instance, if I wanted to grab some data from this, some data in this homepage.

Let's say that data was async data, so I'm gonna make this function an async function, and I wanted to get some data. What I'm gonna do is I'm gonna make a function that says getData, right? I'm just gonna make a function that says getData, and it's going to be an async function, and then I'm just going to await a new Promise.

I'm just gonna make a delay here, so we can be dramatic about it. I'm just gonna do a setTimeout of some time or something like that. And it's just gonna resolve, [COUGH] Here, after some time of, let's say two seconds. So, it's just gonna do that and then it's gonna return some data, right?

And then it'll say, cool, here's some data, here's your data, right? So now I can go in here and say, cool, give my data, and I can await that. You've never been able to do this in React. I've never been able to do async await inside of a component.

You couldn't do it because of the reasons I just showed you. It has to be synchronous, it has to return some JSX. It's not going to keep track of stuff, you got to use hooks if you want to do things and that's just because how React does reconciliation and keeping the render cycle clean.

Imagine if React had to wait for your component to get some data before it could render it, your app would be so slow, no one would ever use it. It wouldn't work, right? Okay, but on the server, it's cool, it's fine, it doesn't matter. So now I can do that, and I can get the data, and I can do whatever I want with the data, right?

So, you can use that data, I'm just gonna log in. All right, so now I can just log that data like that. I don't know, I'm just gonna do it this way. It's how I do it anyway. There we go, then export default Home.
>> You're not returning anything in the res or result?

Or response, I mean.
>> No, this should be fine. This doesn't matter. That's just TypeScript freaking out. I think it's another page, I'm just checking my pages right quick.
>> In the marketing folder, aren't there conflicting page.tsx files?
>> There is, I added those, there it is. See, I ran into that.

Actually, I don't even need this marketing folder. That is more likely because I feel like it wasn't even showing the page that I was interested in. So there we go, got rid of that. Now I have to restart it. It doesn't like when you delete files and then try to do it again.

Okay, there we go. Yeah, and this is why you don't have conflicts. So I think that's why I didn't add the JSX in those pages the first time cuz I didn't want the conflict. But then it started tripping because I didn't have JSX in it, which then caused the conflict.

So now we can await it for two seconds, we can await this data, we can log it, and then we can kind of see what happens. So you can see it's already taken longer, that took two seconds, and then you can see the data is here on the server side.

So it's not logging here in the console, in the browser, right? Because it's server side, so it's gonna lock in a terminal, yeah.
>> This might be premature, but are there caching or techniques to deal with, like the overhead of making the extra, just the latency of making a second API call to get data?

>> So are you talking about issues here-
>> Yeah, I'm assuming that there'll be one server that's running Next, and then another API server that actually gates the database.
>> Yeah, so you can talk directly to your database here if you want to. So if you have an ORM, just import your ORM and talk to your database right here.

So you can just do a SQL query or whatever query you want right here. But if there was a third party API that you wanted to talk to you that was behind that, then yeah, so there's built-in caching. And I kind of talked about earlier, but if you go to, its advanced, so wait, hold on, before I talk about it, I think I am gonna talk about some of it.

Let me just double check before I get in there. No, I'm not gonna talk too much about it because it is very complex. So I'll just show you right now. Basically, if you use the fetch function that's built into Next.js, you have full control over how it's cached, and when it's cached, and where it's cached, and you have the ability to do tons of revalidating on it.

So, they have a whole article about their caching strategy, and again, I could talk a week just about this, it's very complicated. But if you use the built-in fetch, which is a modified version of the fetch that you know, you get control over how things revalidate, where they revalidate, what paths revalidate them.

And this is just not for fetching, this is actually for every single page that we make, it is cached by default by that path, and we get full control over how we revalidate that page given a path by using a revalidate handler like revalidate tag or things like that.

We can actually force it to revalidate a page, which we will do today when we do server actions. So, it's very complicated, but yes, you can limit that caching. You can also just do your own caching that you want yourself. If you want to hook up Redis and bring Redis right into this function, you can do that because this is just Node.

So, whatever you can do on Express or any server side Node technologies, you can bring in here as well. So, it's kind of crazy to think about that you have Redis running inside of a component, but yeah, you can because it's just happens on the server.
>> That's what I was wondering, thanks.

>> Yeah.
>> But you don't need like a separate Express server for PG or for the Redis?
>> No, no, no you don't. Yeah, we're actually about to install a database right now and use it, yeah. [LAUGH] Yeah, cool.

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