This course has been updated! We now recommend you take the Introduction to Next.js 13+, v3 course.

Check out a free preview of the full Introduction to Next.js 13+, v2 course:
The "Loading Page" Lesson is part of the full, Introduction to Next.js 13+, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Scott demonstrates handling a loading state using special pages provided by Next.js to handle loading and error states. A demonstration of using Suspense to manually set up a loading state is also provided in this segment.

Get Unlimited Access Now

Transcript from the "Loading Page" Lesson

>> So now, more on the data fetching. So, I said, I think there was a question earlier if we were gonna get to handling errors, or things like that. Well, yes, so we got some more special pages. I know we talked about the head component, we talked about layouts, I mentioned templates, there's a few more.

[00:00:18] I think there's like three or four more. There's really only two I wanna talk about, and one of them is gonna be the loading page, which I think is super powerful. So, the loading page is exactly what it sounds like, it's a page that will basically show some type of loading indicator, while a server component is trying to fetch its data.

[00:00:40] And if you think about the nested nature of how we can do server components, I don't know, you might have something on a page that's got tile zone and each one of those tiles is a server component. And if they're loading individually, you can show a different loading UI for each one of those things individually, just by making another page, which is pretty helpful.

[00:00:58] And we get this for free just by tapping into some of the syntax. So, let's give it a shot, so let me over exaggerate, loading right quick. So, this is what I'll do. I'll actually make this function right here. Well actually what I'll do, I'll just go up here, and I'll make something called wait, or call it delay.

[00:01:17] Something like that, and then delay returns a new promise. That takes a callback, takes a resolve. And it takes a setTimeout. It's gonna pass something there, and then it'll take a time. Cool, so now we can wait, and then I'll just say delay. We'll just delay you for, let's just over exaggerate this, five seconds.

[00:01:49] And delay for five seconds, and then we'll just return some object here, doesn't matter. Something like that, okay? So we're gonna delay this five seconds. While this is waiting, let's see what happens, we'll just do this, we'll say post slug, and we'll just see how long it takes to get back, right, so let's go here.

[00:02:19] You see it's still spinning, it's still spinning, still spinning. And boom, there it went, right, it took five seconds for that to come back because we delayed it for a while. You can see, right, I just reloaded it, sort of seeing there it is, and then it came back.

[00:02:36] It's just the same data, so that's why it's showing that. So what we wanna do, instead of having nothing to show while it's loading, it's cached now because I'm local, we can do a loading page instead. So I can come here, and I can say loading.tsx. And I can put whatever I want here, so I can say exports default, function, blog, or post loading, something like that.

[00:03:08] And I could return whatever I want. This is where you would show like a skeleton, or not a Halloween skeleton, but a-
>> [LAUGH]
>> You guys know what I'm talking about, like the loading skeletons?
>> Yeah, a shimmer.
>> Shimmer, that's another word for it, yeah. Yeah, I should probably start calling it shimmer, because when I say skeleton, people are like, what are you talking about?

[00:03:26] I'm talking about, yeah, let me just see if I can find a good example of it, like that thing, and it kind of does this thing, yeah, shimmer, shimmer is a better word. So, yeah, this is where he would show that, right, so I'm just gonna say loading though, right?

[00:03:42] So we'll just do loading like that, and let's see if it works here, there we go. So it's loading, it's loading, and then boom it came back, right? So this is a great place but notice, this didn't move this UI bit, all right? So, it's independent, and we have many of these on the page, all loading individually, doing whatever they want, and everything else is still there just waiting.

[00:04:03] So you don't have to wait for your whole app to load up, I never wanna go to an app and see the whole screen just be a loading thing in the middle again, there's no reason to do that anymore. In fact, you didn't have to do that before, it was just a lot of work to set up.

[00:04:17] It was just like, you gotta move this API call to this thing and it was just a lot of work, people didn't do it. It wasn't that it wasn't possible, it was just that most of the time we fetch our data at the page level, the container level, the controller level, and never on the leaf level.

[00:04:34] But now we are fetching on a leaf level, and they're completely independent of themselves. You can almost think of it as like the movement of like, all right, we're gonna put everything in one component. But then we were like, no, let's make smaller UI components, and have scoped CSS.

[00:04:49] And we're gonna have our tests and everything over here just for this component. Now we're saying, now we're gonna put the data fetching in that component as well. So everything goes in that component, and you can think of a component as its own little isolated app almost. So that's kind of where we are with that.

[00:05:03] So, that's the loading one, it's pretty cool. Really what all this is doing, is using something called suspense, right? If you never heard of suspense in React, it basically is like, it's a way that you can stream a component to the front end. And while it's streaming, or while it's loading, you can show a loading fallback until it's ready, basically.

[00:05:32] It's like the cool if you did a set state, or sorry, like a use state hook, that says it's loading. And then, soon as you fire off the event you say, is loading true, that re renders and shows a loading thing. And then when it comes back you say, is loading false?

[00:05:48] And then it shows the data that came back, it's the equivalent of doing all of that. Just creating a wall file, for free, right? So, that's how that works. So other examples if you wanted to bring in a server component to another server component, but you want it to wait on it, and you want it to load instead, right?

[00:06:06] So for instance, if I made a server component over here, I know I have one, yeah, header link. So if I had header link, actually I'll just make all these server components, it's so much easier. So, and then, inside of page, if header was going to take a long time to show, I could put a suspense around this.

[00:06:30] So, it's not a blank until it shows up, right? So for instance, I can go to header. I can say, let me get that, where's that thing at? This thing, come here, get over here. I'm gonna just move this up, I'm going to make a new folder here.

[00:06:51] You can make whatever folders you want on the root by the way. I always like to make one called lib or something like that for all my non component library things. Now let's call this delay. Put that in there and export it. Okay, cool, so we got that, and then what I can do, is I can go into header, and I can say, I don't know, let's just be weird here, and just say await.

[00:07:26] Wait delay for another five seconds like that. And then inside of the page in which I am using this, which I believe is the index page, you can see right now, don't worry about this type script error. This is a known error, there's a specific comment you can put in here to tell typescript, chill out.

[00:07:50] I know it returns a promise, I get it. But, yeah, in the meantime, we can do what's called a suspense. So I'm gonna say suspense like this, like that, and then you can say fall back, and you can put some loading component in here. So, Don't have one, I guess I could just make one right quick.

[00:08:13] Or I'll just take this one. Loading. Let's put this one in here, export that. Loader, go back into the page, and I can say this is going to be loader. Right, so, and you can make the loader a client component, actually, which is totally fine. I think maybe it even needs to, let's see.

[00:08:44] We're gonna find out, I think it needs to be one. So we'll do that, and I'll just go to home, and you can see it's loading, showing the loader for the header, and then when it's done, the header comes back, right? And I did that manually using the suspense right here, which is exactly what the layout file does for you automatically.

[00:09:06] And that only works for pages in the pages directory, but in this case, I had a component that was not in the pages directory that I imported myself. So I had to manually use suspense to set up a loading state for it, but you get it for free, if you use the loading page in the app directory.

[00:09:27] I set page directory earlier, I meant app directory, sorry, I'm still getting used to saying app directory. Cool, any questions on this? No, if you've never seen suspense before, this is what it looks like. It's not as scary as it sounds, I mean, it's actually really quite cool, you should go read about it.

[00:09:46] But, yeah, that's all it's doing is just show this thing until this thing is ready, cuz it's an async loading component, right? Before server component and stuff, suspense was mainly used for dynamically imported component, right? Using dynamic imports for route code splitting, route splitting, stuff like that, and you would suspense that.

[00:10:10] But now we're doing it for data fetching purposes on the server. So, same result, well, different result ultimately but still using suspense to solve a common problem of something not here yet. And showing a loader until it gets here. Cool, yeah.
>> So the naming convention is such that everything is, all the files are lower case, except for the component files?

>> That's just my convention, yeah, I'm kind of weird. I guess I was using React back in the day where we used capital letters for our components, but I don't know, I feel like a lot of folks these days just use lowercase for everything. And maybe I should switch to that, because you actually have to keep them lowercase in the app directory.

[00:10:52] But I've always just been used to keeping them uppercase in the components. For some reason I've just done that because when I see that, I know that that's a component and not a page. Whereas when I see these, I know that these are, I mean, it literally says page, but before you have to use the word page, you just didn't know, for instance down in the pages directory like hello TS, that's a page, because you don't have to use page JS in the pages directory.

[00:11:17] But I know it's a page because it's also lowercase. Whereas, if it was uppercase, and not in this folder, then I would know, so, that's mostly just me. And I also think it's out of habit of like, sometimes, a while ago, people didn't use the actual JSX or TSX extension, they just use .js, or .ts, and that still works.

[00:11:39] You don't actually have to change it to TSX or JSX. But then it's like, well what's the difference between a regular TS file that didn't have JavaScript in it and a TS file that had JSX in it? So sometimes they will capitalize the letter of the file, so, if you look at that's a component.

[00:11:56] And the other one's just a regular JavaScript file, versus just using the different extensions cuz they were lazy. So, yeah, it's history to it, but it's just my thing, it's just what I've done. I'm not saying it's right or wrong.