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

如何为基于本地无分页JSON的NextJS应用实现URL同步分页

基于本地JSON的NextJS分页实现方案(URL同步版)

核心思路

利用NextJS的路由参数管控页码,结合slice处理本地数据,确保URL随页码实时变化,支持页面刷新、前进后退时保留分页状态。

具体实现步骤

1. 加载本地JSON数据

假设JSON文件存放在data/products.json,先在组件中读取数据:

import productsData from '../data/products.json';
const products = Object.values(productsData);

2. App Router(NextJS 13+)实现方案

'use client';
import { useSearchParams, useRouter } from 'next/navigation';
import Product from './Product';

export default function ProductsPage() {
  const searchParams = useSearchParams();
  const router = useRouter();
  const itemsPerPage = 10;
  
  // 获取当前页码,默认显示第1页
  const currentPage = parseInt(searchParams.get('page')) || 1;
  // 计算当前页数据的起始/结束索引
  const startIndex = (currentPage - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  const currentProducts = products.slice(startIndex, endIndex);
  
  // 计算总页数
  const totalPages = Math.ceil(products.length / itemsPerPage);

  // 页码切换逻辑
  const goToPage = (page) => {
    if (page < 1 || page > totalPages) return;
    const params = new URLSearchParams(searchParams);
    params.set('page', page);
    router.push(`/?${params.toString()}`);
  };

  return (
    <div>
      <div className="products-grid">
        {currentProducts.map((item) => (
          <Product {...item} key={item.id} /> {/* 优先用产品唯一ID作为key,避免index引发的渲染问题 */}
        ))}
      </div>

      {/* 分页控件 */}
      <div className="pagination">
        <button onClick={() => goToPage(currentPage - 1)} disabled={currentPage === 1}>
          上一页
        </button>
        {Array.from({ length: totalPages }, (_, i) => i + 1).map(page => (
          <button 
            key={page} 
            onClick={() => goToPage(page)}
            style={{ backgroundColor: currentPage === page ? '#0070f3' : 'transparent', color: currentPage === page ? '#fff' : '#000' }}
          >
            {page}
          </button>
        ))}
        <button onClick={() => goToPage(currentPage + 1)} disabled={currentPage === totalPages}>
          下一页
        </button>
      </div>
    </div>
  );
}

3. Pages Router(旧版)兼容方案

import { useRouter } from 'next/router';
import Product from './Product';
import productsData from '../data/products.json';

export default function ProductsPage() {
  const router = useRouter();
  const { page = 1 } = router.query;
  const products = Object.values(productsData);
  const itemsPerPage = 10;
  const currentPage = parseInt(page);
  const startIndex = (currentPage - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  const currentProducts = products.slice(startIndex, endIndex);
  const totalPages = Math.ceil(products.length / itemsPerPage);

  const goToPage = (targetPage) => {
    if (targetPage < 1 || targetPage > totalPages) return;
    router.push({ query: { ...router.query, page: targetPage } });
  };

  // 组件返回结构与App Router版一致,此处省略重复代码
}

关键注意事项

  • URL同步:通过?page=X搜索参数记录页码,刷新页面不会丢失当前页状态,完全符合NextJS路由特性。
  • Key优化:避免用index作为组件key,优先使用产品的唯一标识(如item.id),减少不必要的组件重渲染。
  • 边界校验:添加页码上下限判断,防止非法页码导致数据异常。
  • 静态生成适配:若数据无需频繁更新,可通过getStaticPaths预生成所有分页页面,结合getStaticProps传递对应页码数据:
// Pages Router 静态生成示例
export async function getStaticPaths() {
  const products = Object.values(productsData);
  const itemsPerPage = 10;
  const totalPages = Math.ceil(products.length / itemsPerPage);
  const paths = Array.from({ length: totalPages }, (_, i) => ({
    params: { page: (i + 1).toString() }
  }));
  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const page = parseInt(params.page);
  const itemsPerPage = 10;
  const startIndex = (page - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  const currentProducts = Object.values(productsData).slice(startIndex, endIndex);
  return { 
    props: { 
      products: currentProducts, 
      currentPage: page, 
      totalPages: Math.ceil(productsData.length / itemsPerPage) 
    } 
  };
}

内容的提问来源于stack exchange,提问作者Yakushi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:55:18