Skeleton loader
A skeleton is essentially a lightweight, placeholder layout that mimics the shape of the content being loaded, giving users a visual structure to look at while they wait for the actual content.
Dynamic Imports with Skeletons
For components that are loaded dynamically using next/dynamic, you can provide a skeleton as a fallback while the component is being fetched.
import dynamic from 'next/dynamic';
// Use a Skeleton as a loading placeholder
const DynamicComponent = dynamic(() => import('../components/HeavyComponent'), {
loading: () => <SkeletonCard />, // Show skeleton while loading
});
function HomePage() {
return (
<div>
<h1>Home Page</h1>
<DynamicComponent />
</div>
);
}
export default HomePage;
Using Server Components and Suspense with Skeletons
- Create a Skeleton Component: This component mimics the layout of the actual content and is displayed while data is loading.
- Create an Async Component to Fetch Data: Use a server component to fetch the data, and wrap it with React’s
<Suspense>to show the skeleton while loading. - Use the Async Component in the Page: Integrate the server-side fetched component with Suspense and the Skeleton.
import { Suspense } from 'react';
import CourseSkeleton from './CourseSkeleton';
// Server Component to fetch and display courses
async function CourseList() {
const courses = await fetchCourses(); // Fetch data on the server
return (
<div className="course-list">
{courses.map((course) => (
<div key={course.id} className="course-card">
<div className="course-image">{/ Display course image /}</div>
<h2>{course.name}</h2>
<p>Price: ${course.price}</p>
</div>
))}
</div>
);
}
// Page component that uses Suspense with the skeleton
export default function CoursePage() {
return (
<Suspense fallback={<CourseSkeleton />}>
<CourseList />
</Suspense>
);
}