How to Create Pagination in Next.js with Shadcn UI

Candra Kriswinarto
3 min readOct 16, 2024

--

Photo by Austin Distel on Unsplash

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!

--

--

Candra Kriswinarto
Candra Kriswinarto

Written by Candra Kriswinarto

👋 Front-End Developer & YouTuber. I write about web dev, share coding tips, and create tutorials to help others learn. https://youtube.com/@CandDev

No responses yet