How to Create Pagination in Next.js with Shadcn UI
In this tutorial, we’ll walk through the process of creating a pagination component in Next.js using Shadcn UI. We’ll build a paginated list of posts fetched from an API, with the ability to change the number of posts per page.
You can see a preview of what we’re going to build here: https://nextjs-paginate-five.vercel.app/
If you prefer a video tutorial, you can watch it here: YouTube Tutorial
Let’s get started!
Step 1: Set up the Project
First, let’s create a new Next.js project:
npx create-next-app@latest nextjs-paginate
Next, initialize Shadcn UI:
npx shadcn@latest init
Step 2: Install Required Components
We’ll need the pagination, select, and card components from Shadcn UI:
npx shadcn@latest add pagination select card
Step 3: Create API Utility Functions
Create a new file lib/api.ts
and add the following code:
import { post } from "./types";
export async function fetchPosts(page: number, perPage: number) {
const start = (page - 1) * perPage;
const res = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${perPage}`);
const posts: post[] = await res.json();
const totalPosts = parseInt(res.headers.get('X-Total-Count') || '0');
return { posts, totalPosts }
}
This function fetches posts from the JSONPlaceholder API, calculating the correct starting point based on the current page and number of posts per page. It returns both the posts and the total count of posts.
Now, create lib/types.ts
and add the following:
export interface post {
id: number,
title: string,
body: string
}
This defines the structure of a post object.
Step 4: Create the Pagination Component
Copy the pagination-with-links.tsx
component from the components/ui/
directory in the GitHub repository and paste it into the same path (components/ui/pagination-with-links.tsx)
in your app.
Step 5: Create the Posts Component
Create a new file components/posts.tsx
and add the following code:
import { fetchPosts } from '@/lib/api';
import PostList from './post-list';
import { PaginationWithLinks } from './ui/pagination-with-links';
interface PostsProps {
searchParams: { [key: string]: string | undefined };
}
export default async function Posts({ searchParams }: PostsProps) {
const currentPage = parseInt((searchParams.page as string) || '1');
const postsPerPage = parseInt((searchParams.pageSize as string) || '5');
const { posts, totalPosts } = await fetchPosts(currentPage, postsPerPage);
return (
<div className='my-8'>
<h1 className='text-3xl font-bold mb-6'>Posts</h1>
<PostList posts={posts} />
<div className='mt-8'>
<PaginationWithLinks
page={currentPage}
pageSize={postsPerPage}
totalCount={totalPosts}
pageSizeSelectOptions={{
pageSizeOptions: [5, 10, 25, 50],
}}
/>
</div>
</div>
);
}
This component fetches posts based on the current page and posts per page, then renders the post list and pagination component.
The PaginationWithLinks
component handles the pagination logic. When you click a page button, it adds a page={numberSelected}
parameter to the URL. When you change the number of posts per page using the select dropdown, it adds a pageSize={numberSelected}
parameter.
Step 6: Create the PostList Component
Create a new file components/post-list.tsx
and add the following code:
import { post } from '@/lib/types';
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
interface PostListProps {
posts: post[];
}
export default function PostList({ posts }: PostListProps) {
return (
<div className='space-y-4'>
{posts.map((post) => (
<Card key={post.id}>
<CardHeader>
<CardTitle>{`${post.title} (post ${post.id})`}</CardTitle>
</CardHeader>
<CardContent>{post.body}</CardContent>
</Card>
))}
</div>
);
}
This component renders each post as a card using Shadcn UI’s Card component.
Conclusion
That’s it! You’ve now created a paginated list of posts in Next.js using Shadcn UI. The pagination component allows users to navigate through pages and change the number of posts displayed per page.
For the full code of this project, you can check out this GitHub repository: https://github.com/candraKriswinarto/nextjs-paginate
Feel free to customize the components and styling to fit your specific needs. Happy coding!