Usage
import { usePagination } from '@kivora/react';
function DataTable({ items }: { items: any[] }) {
const { activePage, range, setPage, next, previous } = usePagination({
total: items.length,
pageSize: 10,
initialPage: 1
});
const startIndex = (activePage - 1) * 10;
const pageItems = items.slice(startIndex, startIndex + 10);
return (
<div>
<table>
{pageItems.map((item, i) => (
<tr key={i}><td>{item}</td></tr>
))}
</table>
<div>
<button onClick={previous}>Previous</button>
{range.map((page, index) =>
page === 'dots' ? (
<span key={`dots-${index}`}>...</span>
) : (
<button
key={page}
onClick={() => setPage(page)}
disabled={page === activePage}
>
{page}
</button>
)
)}
<button onClick={next}>Next</button>
</div>
</div>
);
}
Parameters
options
UsePaginationOptions
required
Configuration object for pagination
Initial active page (1-based)
Number of sibling pages shown on each side of the active page
Number of boundary pages shown at start and end
Return Value
Current active page (1-based)
Array of page numbers and ‘dots’ placeholders for the pagination UI. Example: [1, 'dots', 5, 6, 7, 'dots', 20]
Set the active page. Value is clamped between 1 and totalPages.
Navigate to the next page (if not on last page)
Navigate to the previous page (if not on first page)
Navigate to the first page
Navigate to the last page
Examples
const items = Array.from({ length: 100 }, (_, i) => `Item ${i + 1}`);
const pagination = usePagination({ total: items.length, pageSize: 10 });
const startIndex = (pagination.activePage - 1) * 10;
const currentItems = items.slice(startIndex, startIndex + 10);
return (
<div>
{currentItems.map(item => <div key={item}>{item}</div>)}
<p>Page {pagination.activePage} of {pagination.totalPages}</p>
</div>
);
Custom Page Range
const pagination = usePagination({
total: 1000,
pageSize: 20,
siblings: 2, // Show 2 pages on each side
boundaries: 2 // Show 2 pages at start/end
});
// Range might look like: [1, 2, 'dots', 8, 9, 10, 11, 12, 'dots', 49, 50]
const { activePage, totalPages, next, previous, first, last } = usePagination({
total: 200,
pageSize: 10
});
return (
<div>
<button onClick={first} disabled={activePage === 1}>
First
</button>
<button onClick={previous} disabled={activePage === 1}>
Previous
</button>
<span>
Page {activePage} of {totalPages}
</span>
<button onClick={next} disabled={activePage === totalPages}>
Next
</button>
<button onClick={last} disabled={activePage === totalPages}>
Last
</button>
</div>
);
const [data, setData] = useState([]);
const [totalItems, setTotalItems] = useState(0);
const pagination = usePagination({
total: totalItems,
pageSize: 20,
initialPage: 1
});
useEffect(() => {
fetch(`/api/items?page=${pagination.activePage}&size=20`)
.then(r => r.json())
.then(response => {
setData(response.items);
setTotalItems(response.total);
});
}, [pagination.activePage]);
function Pagination() {
const { activePage, range, setPage, next, previous } = usePagination({
total: 500,
pageSize: 10,
siblings: 1,
boundaries: 1
});
return (
<nav>
<button onClick={previous} disabled={activePage === 1}>
← Prev
</button>
{range.map((page, index) => {
if (page === 'dots') {
return <span key={`dots-${index}`}>...</span>;
}
return (
<button
key={page}
onClick={() => setPage(page)}
className={page === activePage ? 'active' : ''}
>
{page}
</button>
);
})}
<button onClick={next} disabled={activePage === range[range.length - 1]}>
Next →
</button>
</nav>
);
}
With URL Sync
const [searchParams, setSearchParams] = useSearchParams();
const pageFromUrl = Number(searchParams.get('page')) || 1;
const pagination = usePagination({
total: 300,
pageSize: 15,
initialPage: pageFromUrl
});
// Sync page changes to URL
useEffect(() => {
setSearchParams({ page: String(pagination.activePage) });
}, [pagination.activePage, setSearchParams]);