
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.
When your app fetches data or performs operations that take time, showing a loading state improves user experience. Users don’t have to wait for seconds to see a blank screen that way; rather, they can see something, some skeletons or spinners, and know that they have to wait a bit to see what they’re looking for.
To do that, especially for pages that do server-side rendering, you can use a special loading.js file that creates an automatic loading UI for your routes. When you add this file to a folder, it acts as a loading state while the page layout in that folder is being loaded.
Did you think you would have to turn the whole component into the client side to show loadings using states? Nah, dummy.
By placing this file inside a route segment's folder within the app directory, Next.js automatically wraps the corresponding page.js and any nested children with a <Suspense> boundary, displaying the fallback UI defined in loading.js while the content is loading.
React's Suspense is a built-in component that allows you to display a fallback UI. It lets you "pause" the rendering of a component tree until certain conditions are met—typically until data is fetched or a component is loaded.
During this pause, a fallback UI is displayed. Once the required data or component is ready, React renders the actual content.
As we’ve seen before, a basic example of Suspense looks like this:
import React, { Suspense } from 'react';
import Profile from "./profile";
function App() {
return (
<Suspense fallback={<div>Loading profile...</div>}>
<Profile />
</Suspense>
);
}
You’ve already done this before—for the Vote component on both Question and Answer cards and even when saving a question to a collection. If it’s a bit fuzzy, feel free to take a quick look back.
But wait—does that mean loading.js is the only way to show a loading UI on your pages?
What if you just want to load a part of the page, not the whole thing?
Great question.
Think back—we’ve actually done this before. Remember the stats section on the question details page? Yep, you used a simple “…” loader with React Suspense to show that. That’s basically what loading.js does, too—just behind the scenes.
If you need loading for the entire page, just drop a loading.tsx file inside that route’s folder. But if you only want to load a specific part, React Suspense is your go-to.
For client components, you already know the usual way—using state to manage loading. But if that feels messy or too manual, you can level up with tools like TanStack Query, which handles fetching, errors, and loading states more smoothly.
Now, let's see how loading.js/ts/tsx/jsx works in action.
To display skeletons while data is loading, you can either create your own UI with Tailwind CSS or use ShadCN skeletons.
I'll be using ShadCN skeletons. To get started, open your terminal and run:
npx shadcn@latest add skeleton
Next, create a new loading.tsx file inside the app/(root)/community/page.tsx folder and set up a skeleton UI like this:
import { Skeleton } from "@/components/ui/skeleton";
const Loading = () => {
return (
<section>
<h1 className="h1-bold text-dark100_light900">All Users</h1>
<div className="mt-11 flex justify-between gap-5 max-sm:flex-col sm:items-center">
<Skeleton className="h-14 flex-1" />
<Skeleton className="h-14 w-28" />
</div>
<div className="mt-12 flex flex-wrap gap-5">
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => (
<Skeleton
key={item}
className="h-60 w-full rounded-2xl xs:w-[230px]"
/>
))}
</div>
</section>
);
};
export default Loading;
Nothing too fancy—just the same styles and layout as app/(root)/community/page.tsx, but this time you’re using skeletons instead of components.
Save your changes, then head over to http://localhost:3000/community to see the loading in action.
It’s that simple!
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.
00:00:00 Let's implement loadings, this time with Shazien's skeleton component.
00:00:06 A component that allows you to show a placeholder while the real content is loading.
00:00:11 You think something is loading here?
00:00:13 Well, not really.
00:00:14 That's just a placeholder.
00:00:16 So let's add it by copying this command to our terminal.
00:00:20 That's going to be mpx shazien add latest add skeleton.
00:00:26 There we go, it got added immediately.
00:00:29 And now we can also copy its usage, which is super simple.
00:00:33 The question is, where do we want to add it though?
00:00:36 Let's start with the community page first.
00:00:38 So I'll head over into app, root, community, and I'll create a new special file called loading.tsx.
00:00:49 And within it, I'll run RAFCE.
00:00:52 What we have to do here is match the layout of our page as closely as possible.
00:00:57 And that should look something like this.
00:01:00 We open up the loading where we have a section.
00:01:02 We have an H1 at the top, a div with two skeletons, and then we map over 10 more skeletons to show the content that is coming up.
00:01:10 If you head back over here and head over to the community page, this is the layout we're trying to replicate.
00:01:15 A skeleton for the search.
00:01:17 for the filters, and then the actual users.
00:01:19 For the heading, we don't even have to have a skeleton, because this text will always be the same, so we can make it show immediately.
00:01:27 And now having this new loading.tsx file with the skeleton layout, if you just reload, check this out.
00:01:33 Well, now my internet has already cached the previous data, but while I was doing the first reload, you should have been able to see a shimmer on these
00:01:41 components as they were appearing to be loaded in.
00:01:43 And with that, we have just added loading skeletons and made it work for the community page.