I am working on a React component that fetches NFT data and displays it in a paginated table. However, I'm having trouble with the pagination navigation. Specifically, I want to show all available pages as clickable numbers (e.g., 1, 2, 3, 4, ..., 147) so that users can navigate to any specific page directly. Currently, the pagination is not working as expected, and I need help to display all page numbers correctly.
"use client";
import { useEffect, useState } from 'react';
import Link from 'next/link';
import styles from '../page.module.css';
import Form from 'react-bootstrap/Form';
const NftData = () => {
const [cryptoData, setCryptoData] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(20);
useEffect(() => {
fetch(`https://apicall.trabic.com/api/v1/nft/getNFT?page=${currentPage}&itemsPerPage=${itemsPerPage}`)
.then((response) => response.json())
.then((data) => setCryptoData(data))
.catch((error) => console.error('Error fetching data:', error));
}, [currentPage, itemsPerPage]);
const totalPages = Math.ceil(cryptoData.length / itemsPerPage);
const handlePageChange = (page: number) => {
if (page > 0 && page <= totalPages) {
setCurrentPage(page);
}
};
return (
<div className='container'>
<table className={`${styles.tableStl} table`}>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">NFT</th>
<th scope="col">Floor Price</th>
<th scope="col">24h Change</th>
<th scope="col">24h Volume</th>
<th scope="col">Owners</th>
<th scope="col">Assets Change</th>
<th scope="col">Timestamp</th>
</tr>
</thead>
<tbody>
{cryptoData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage).map((crypto: any) => (
<tr key={crypto.index}>
<th scope="row">{crypto.index}</th>
<td>{crypto.nft}</td>
<td>{crypto.floor_price}</td>
<td className={crypto.total_24h.startsWith('-') ? 'text-danger' : 'text-success'}>
{crypto.total_24h}
</td>
<td>{crypto.total_24h_volume}</td>
<td>{crypto.owners}</td>
<td className={crypto.total_assets.startsWith('-') ? 'text-danger' : 'text-success'}>
{crypto.total_assets}
</td>
<td>{new Date(crypto.time_stamp).toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
<div className='container'>
<div className='row'>
<div className='col-md-3 col-12'>
<p className='float-start fs-6 textPara'>
Showing {(currentPage - 1) * itemsPerPage + 1} to {Math.min(currentPage * itemsPerPage, cryptoData.length)} of {cryptoData.length} results
</p>
</div>
<div className='col-md-6 col-12'>
<nav aria-label="Page navigation example my-3">
<ul className="pagination d-flex justify-content-center">
<li className="page-item">
<Link href="#" aria-label="Previous" onClick={() => handlePageChange(currentPage - 1)}>
<span aria-hidden="true">«</span>
</Link>
</li>
{Array.from({ length: totalPages }, (_, index) => index + 1).map(pageNumber => (
<li key={pageNumber} className="page-item">
<Link
href="#"
className={`page-link ${pageNumber === currentPage ? 'active' : ''}`}
onClick={() => handlePageChange(pageNumber)}
>
{pageNumber}
</Link>
</li>
))}
<li className="page-item">
<Link href="#" aria-label="Next" onClick={() => handlePageChange(currentPage + 1)}>
<span aria-hidden="true">»</span>
</Link>
</li>
</ul>
</nav>
</div>
<div className='col-md-3 col-12'>
<Form.Select size="lg" className='float-end w-25' onChange={(e) => {
setItemsPerPage(parseInt(e.target.value));
setCurrentPage(1); // Reset current page to 1 when items per page changes
}}>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="300">300</option>
</Form.Select>
</div>
</div>
</div>
</div>
);
};
export default NftData;