PnP React Pagination Control in SharePoint Framework (SPFx) Web Part

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 NameDataTypeDescription
currentPagenumberThe page is initially selected.
totalPagesnumberTotal number of pages available.
onChangestringA function that runs when the user clicks a different page. It passes the selected page number.
limiternumberIt defines how many page numbers are visible at once before showing the “…” more icon.
hideFirstPageJump booleanHides the quick jump button to the first page.
hideLastPageJump boolean Hides the quick jump button to the last page.
limiterIconstringTo 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.

Paging for SPFx Solutions with PnP Pagination Control

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.

  1. Open the command prompt and run the commands below; it will create a directory for our solution.
md PnPReactPaginationDemo

cd PnPReactPaginationDemo
  1. Run the Yemon generator command to scaffold the SPFx solution.
yo @microsoft/sharepoint
  1. 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
Pagination in spfx webpart
  1. Once the solution has been created successfully, install the command below.
npm install @pnp/spfx-controls-react --save --save-exact
Pagination from SPFx
  1. Then run the command below to open the code in Visual Studio Code.
code .
  1. 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.
  1. 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:

Live Webinar

Build an IT Help Desk App using Power Apps and Power Automate

Join this free live session and learn how to build a fully functional IT Help Desk application using Power Apps and Power Automate—step by step.

📅 29th Apr 2026 – 10:00 AM EST | 7:30 PM IST

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App

Power Platform Tutorial

FREE Power Platform Tutorial PDF

Download 135+ Pages FREE PDF on Microsoft Power Platform Tutorial. Learn Now…