You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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">&laquo;</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">&raquo;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:35:03