Recently, I was working with a client on a SPFx client-side web part to display a large number of items from a SharePoint list. The SharePoint list contains more than 10,000 items. So, it is not a good idea to load all the list items inside the web part and display them to the users.
The best way to display items from a large SharePoint list is to use pagination, so users can view items by clicking the pagination buttons.
Instead of building pagination manually, we can use the PnP React pagination control in SPFx.
In this tutorial, I will explain how to use the PnP React pagination control in a SharePoint Framework web part to display items from a large SharePoint list.
Before building the complete web part, let me first explain what this PnP React pagination control is.
PnP React Pagination Control
The PnP React Pagination Control is a reusable React component from the @pnp/spfx-controls-react package that provides pagination functionality for SharePoint Framework (SPFx) solutions or web parts.
To use PnP React controls, make sure to choose React as the framework while creating the SPFx web part.
Once your SPFx web part is ready, we need to install the following dependency in our SPFx project. Once you install the command below, you can use the PnP React controls inside your SPFx web part.
npm install @pnp/spfx-controls-react --save --save-exact
To use the PnP React Pagination control in SPFx solution, we need to import the following statement.
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
Below is the PnP React Pagination control syntax:
<Pagination
currentPage={3}
totalPages={13}
onChange={(page) => this._getPage(page)}
limiter={3} // Optional - default value 3
hideFirstPageJump // Optional
hideLastPageJump // Optional
limiterIcon={"Emoji12"} // Optional
/>
Here:
| Property Name | DataType | Description |
|---|---|---|
| currentPage | number | The page is initially selected. |
| totalPages | number | Total number of pages available. |
| onChange | string | A function that runs when the user clicks a different page. It passes the selected page number. |
| limiter | number | It defines how many page numbers are visible at once before showing the “…” more icon. |
| hideFirstPageJump | boolean | Hides the quick jump button to the first page. |
| hideLastPageJump | boolean | Hides the quick jump button to the last page. |
| limiterIcon | string | To choose the Fluent UI icon for the “…” for the limiter button. |
Look at the example below, where Im displaying employees’ data in an HTML table, with a PnP React pagination control. The pagination controls show page numbers and next and previous icons, and highlight the current page.

Use PnP React Pagination Control in SPFx Web Part
Follow the steps below to use the PnP React pagination control in an SPFx web part. First, follow the steps below to create your SPFx client-side web part.
- Open the command prompt and run the commands below; it will create a directory for our solution.
md PnPReactPaginationDemo
cd PnPReactPaginationDemo
- Run the Yemon generator command to scaffold the SPFx solution.
yo @microsoft/sharepoint
- Then it will ask the following questions; answer them as I have below.
- What is your solution name? Click Enter for the default solution name.
- Which type of client-side component to create? WebPart
- Add new Web part to solution pn-p-react-pagination-demo.
- What is your Web part name? PnPPaginationDemo
- Which template would you like to use? React

- Once the solution has been created successfully, install the command below.
npm install @pnp/spfx-controls-react --save --save-exact

- Then run the command below to open the code in Visual Studio Code.
code .
- Now, open the “PnPPaginationDemo.tsx” file located in the src folder.
import * as React from 'react';
import styles from './PnPPaginationDemo.module.scss';
import type { IPnPPaginationDemoProps } from './IPnPPaginationDemoProps';
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
interface IItem {
id: number;
employeeName: string;
department: string;
location: string;
joiningDate: string;
}
interface IPnPPaginationDemoState {
items: IItem[];
currentPage: number;
totalPages: number;
itemsPerPage: number;
}
export default class PnPPaginationDemo extends React.Component<IPnPPaginationDemoProps,IPnPPaginationDemoState> {
constructor(props: IPnPPaginationDemoProps) {
super(props);
const allItems = this._generateItems(100);
const itemsPerPage = 10;
const totalPages = Math.ceil(allItems.length / itemsPerPage);
this.state = {
items: allItems,
currentPage: 1,
totalPages,
itemsPerPage,
};
}
private _generateItems(count: number): IItem[] {
const departments = ["HR", "Finance", "IT", "Marketing", "Sales"];
const locations = ["Bangalore", "Hyderabad", "Chennai", "Pune", "Mumbai"];
const items: IItem[] = [];
for (let i = 1; i <= count; i++) {
items.push({
id: i,
employeeName: `Employee_${i}`,
department: departments[Math.floor(Math.random() * departments.length)],
location: locations[Math.floor(Math.random() * locations.length)],
joiningDate: new Date(2024, Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1).toLocaleDateString(),
});
}
return items;
}
private _getPage = (page: number): void => {
this.setState({ currentPage: page });
};
public render(): React.ReactElement<IPnPPaginationDemoProps> {
const { items, currentPage, itemsPerPage, totalPages } = this.state;
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const currentItems = items.slice(startIndex, endIndex);
return (
<section className={`${styles.pnPPaginationDemo} `}>
<div className={styles.paginationExample}>
<h2 className={styles.heading}>Employee Directory</h2>
<table className={styles.table}>
<thead>
<tr>
<th>ID</th>
<th>Employee Name</th>
<th>Department</th>
<th>Location</th>
</tr>
</thead>
<tbody>
{currentItems.map((item) => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.employeeName}</td>
<td>{item.department}</td>
<td>{item.location}</td>
</tr>
))}
</tbody>
</table>
{/*PnP Pagination Control */}
<div className={styles.paginationContainer}>
<Pagination
currentPage={currentPage}
totalPages={totalPages}
onChange={this._getPage}
limiter={5}
hideFirstPageJump={false}
hideLastPageJump={false}
limiterIcon={"More"}
/>
</div>
</div>
</section>
);
}
}
Here:
- We imported the “Pagination” component from “@pnp/spfx-controls-react”, which provides an easy-to-use pagination UI with built-in functionality.
- IItem = It represents a single record for employee data, and each record has:
- id = Unique ID
- employeeName = Employee Name
- department, location, and joiningDate are the additional details.
- IPnPPaginationDemoState = It defines the states used in this React component.
- items = All records that are generated by the helper method.
- currentPage = The current page number.
- totalPages = Total number of available pages.
- itemsPerPage = How many items are shown on each page.
- The constructor will run when the component loads.
- allItems = This variable contains 100 sample employee data, which is generated by the _generateItems(100) helper method.
- We set ItemsPerPage to 10, so each page displays 10 rows.
- totalPages is automatically calculated based on the total number of items.
- _generateItems(100) = This helper method generates 100 mock employee records. It loops from 1 to the given count of 100, and randomly picks department and local names. Then pushes each record into the array.
- _getPage() = It runs when the user clicks a page number like “3” or “Next” and updates the currentPage in the state.
- In the render() method, we calculate which items to display:
- If we are on page 1, it shows 1-10.
- On page 2, it shows 11-20, and so on.
- This is done by slicing the array from startIndex to endIndex.
- Then, we created a simple HTML <table> and displayed only the current items. Under the table, the PnP Pagination Control is rendered.
- The pagination control:
- Shows the total number of pages.
- Highlights the active page.
- Calls _getPage() when the user changes the page number.
- To add styles, open the .scss file and replace the existing styles with the ones below.
@import '~@fluentui/react/dist/sass/References.scss';
.pnPPaginationDemo {
overflow: hidden;
padding: 1em;
color: "[theme:bodyText, default: #323130]";
color: var(--bodyText);
&.teams {
font-family: $ms-font-family-fallbacks;
}
}
.paginationExample {
padding: 20px;
.heading {
font-size: 20px;
font-weight: 600;
margin-bottom: 15px;
color: #333;
}
.table {
width: 100%;
border-collapse: collapse;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
background-color: #fff;
th {
background-color: #f0f0f0;
padding: 10px;
border: 1px solid #ccc;
text-align: left;
font-weight: bold;
color: #333;
}
td {
padding: 8px;
border: 1px solid #ddd;
color: #444;
}
tr:nth-child(even) {
background-color: #fafafa;
}
tr:hover {
background-color: #f5f5f5;
}
}
.paginationContainer {
margin-top: 20px;
text-align: center;
}
}
That’s it, this way, we use the built-in Pagination control in the SharePoint Framework webpart.
Once the solution is ready, you can also deploy it to the app catalog site and use it.
Conclusion
In this tutorial, I explained how to use the PnP React pagination control in a SharePoint Framework web part to display items from a large list. In this particular example, I have shown how to display more than 10,000 items from a SharePoint list. You can download the SPFx solution and try it out. Do let me know in the comments below if you face any issues.
You may also like the following SPFx tutorials:
- SPFx Fluent UI React Control: ChoiceGroup and Checkbox
- SharePoint Framework (SPFx) Fluent UI Basic List Example
- Fluent UI React ComboBox Control in SPFx
- Fluent UI DocumentCard in SPFx Web Part

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.