React组件分页导航无法显示全部页面问题排查
React NFT分页组件:实现全页码显示的修复方案
问题背景
我正在开发一个React组件,用于获取NFT数据并在分页表格中展示。需求是将所有可用页面(如1、2、3……147)显示为可点击数字,方便用户直接跳转至指定页面,但当前分页未按预期工作,需要修复实现全部页码的正确显示。
原代码核心问题
原代码存在两个关键问题导致页码显示异常:
- 总页数计算错误:用当前页数据条数(
cryptoData.length)计算总页数,而非API返回的总数据条数,导致总页数远小于实际值。 - 前端重复分页:API已返回当前页数据,却在前端再次用
slice处理,逻辑冗余且可能导致数据展示错误。
修复后的完整代码
"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 [nftItems, setNftItems] = useState<any[]>([]); const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(20); const [totalItems, setTotalItems] = useState(0); // 保存总数据条数 useEffect(() => { fetch(`https://apicall.trabic.com/api/v1/nft/getNFT?page=${currentPage}&itemsPerPage=${itemsPerPage}`) .then((response) => response.json()) .then((data) => { // 兼容API返回结构:若返回带total字段的对象则取items,否则直接用数组 setNftItems(data.items || data); setTotalItems(data.total || data.length); }) .catch((error) => console.error('Error fetching data:', error)); }, [currentPage, itemsPerPage]); // 用总数据条数计算真实总页数 const totalPages = Math.ceil(totalItems / 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> {/* 直接渲染当前页数据,无需前端slice */} {nftItems.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, totalItems)} of {totalItems} 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" disabled={currentPage === 1}> <Link href="#" aria-label="Previous" onClick={() => handlePageChange(currentPage - 1)} className="page-link" > <span aria-hidden="true">«</span> </Link> </li> {/* 生成所有可点击页码 */} {Array.from({ length: totalPages }, (_, index) => index + 1).map(pageNumber => ( <li key={pageNumber} className={`page-item ${pageNumber === currentPage ? 'active' : ''}`}> <Link href="#" className="page-link" onClick={() => handlePageChange(pageNumber)} > {pageNumber} </Link> </li> ))} <li className="page-item" disabled={currentPage === totalPages}> <Link href="#" aria-label="Next" onClick={() => handlePageChange(currentPage + 1)} className="page-link" > <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); // 切换每页条数时重置到第一页 }}> <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;
关键修改说明
- 新增总条数状态:添加
totalItems保存API返回的总数据量,确保总页数计算准确。 - 修正总页数计算:用
totalItems / itemsPerPage计算真实总页数,不再依赖当前页数据长度。 - 移除冗余分页逻辑:直接渲染API返回的当前页数据,删除前端
slice处理。 - 优化分页按钮交互:为上一页/下一页添加
disabled属性,避免无效点击。 - 更新统计文本:用
totalItems替代原cryptoData.length,显示正确的总数据量。
内容的提问来源于stack exchange,提问作者Ahmad Arslan
相关产品推荐
相关产品推荐

