Pagination Control in SPFx with PnP React Controls
The SharePoint Framework ecosystem often needs pagination when displaying long datasets such as lists, search results, audit logs, or external APIs. Instead of building pagination logic from scratch, the PnP SPFx React Controls library provides a reusable Pagination control.
This control is lightweight, easy to integrate, and keeps your UI clean.
Why use Pagination?
Pagination improves performance and usability because:
- Reduces rendering overhead.
- Makes navigation easier for users.
- Improves readability in large datasets.
- Works well with APIs, PnPjs, and SharePoint lists.
Common scenarios:
- Paginating SharePoint List items
- Paginating Search Results
- Paginating Audit Logs
- Paginating Microsoft Graph data
Official Documentation
PnP official docs:
PnP Pagination Control Documentation
Related docs:
Installation
Inside your current SPFx solution:
npm install @pnp/spfx-controls-react --savenpm installheft start
Basic Example
Your example demonstrates a static pagination component:
import * as React from 'react';import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";const PaginationControlWp: React.FC = () => { const _getPage = (page: number) => { console.log('Page:', page); }; return ( <Pagination currentPage={3} totalPages={13} onChange={(page) => _getPage(page)} limiter={3} hideFirstPageJump hideLastPageJump limiterIcon={"Emoji12"} /> );};export default PaginationControlWp;
Code Breakdown
Import
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
Imports the reusable Pagination control.
Current Page
currentPage={3}
Defines the currently selected page.
Example:
- Page 1 = first page
- Page 3 = active page
- Page 13 = last page
Total Pages
totalPages={13}
Sets the maximum number of pages.
This is usually calculated like:
Math.ceil(totalItems / pageSize)
Example:
If you have 125 items and 10 per page:
Math.ceil(125 / 10) = 13
Page Change Event
onChange={(page) => _getPage(page)}
Triggered whenever the user clicks another page.
Your handler:
const _getPage = (page: number) => { console.log('Page:', page);};
Real-world usage:
const _getPage = async (page: number) => { const items = await sp.web.lists .getByTitle("Documents") .items .top(10) .skip((page - 1) * 10)(); console.log(items);};
Using PnPjs.
Limiter
limiter={3}
Controls how many page numbers appear around the current page.
Example:
Current page = 6
With limiter 3:
3 4 5 [6] 7 8 9
Without limiter:
1 2 3 4 5 6 7 8 9 10 11 12 13
Cleaner UI.
Hide First Jump
hideFirstPageJump
Removes:
<<
Useful for minimal navigation.
Hide Last Jump
hideLastPageJump
Removes:
>>
Keeps the component simpler.
Custom Limiter Icon
limiterIcon={"Emoji12"}
Uses a Fluent UI icon.
This changes the ellipsis visual.
Example:
Default:
...
Custom:
🙂
Fluent UI icons list:
Real World Integration with SharePoint List
Example with list pagination:
const pageSize = 10;const loadItems = async (page: number) => { const items = await sp.web.lists .getByTitle("Projects") .items .top(pageSize) .skip((page - 1) * pageSize)(); setItems(items);};
Pagination:
<Pagination currentPage={currentPage} totalPages={Math.ceil(totalItems / pageSize)} onChange={loadItems}/>
This is where the control becomes powerful.
Best Practices
Keep page size fixed
Example:
const pageSize = 10;
Avoid random sizes.
Cache results
Avoid re-fetching previous pages.
Combine with filters
Pagination + filters = better UX.
Example:
- Category filter
- Search box
- Sorting
Show loading state
While changing pages:
{loading && <Spinner />}
Use Fluent UI Spinner.
When to Use
Use Pagination when:
✅ More than 20 records
✅ Search results
✅ Large SharePoint lists
✅ External APIs
✅ Graph data
✅ Audit logs
Avoid when:
❌ Small datasets
❌ Static content
❌ Simple dashboards
Final Thoughts
The PnP SPFx React Controls Pagination control saves time and integrates naturally into modern SharePoint Framework solutions.
Your current example is a perfect starting point and can easily evolve into:
- SharePoint List paging
- Graph paging
- Search result paging
- Custom API paging
This control becomes even stronger when combined with:
- PnPjs
- Fluent UI tables
- ListView control
- SearchBox
- Filters
It is one of the most practical controls in the library for enterprise applications.
