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

Next.js加载器仅显示首次加载,分页切换时不触发显示问题

Next.js SSR分页切换时loading.js不显示的解决方案

问题原因

Next.js App Router 中的 loading.js 仅在初始页面加载(如直接访问URL、硬刷新)时触发显示。当通过客户端分页组件使用router.push修改URL的page参数时,属于软导航,Next.js会在后台异步获取新数据,期间保留当前页面内容,不会自动触发loading.js的加载状态。

解决方案

方案1:给分页组件添加客户端加载状态

修改Pagi组件,使用useTransition跟踪导航加载状态,同时显示加载提示并禁用分页交互:

"use client"
import { useState, useEffect, useTransition } from "react";
import { useRouter, useSearchParams } from 'next/navigation';
import {Pagination, PaginationItem, PaginationCursor} from "@nextui-org/react";

export default function Pagi({pages}) {
    // 从URL获取当前页码,避免初始状态与URL不一致
    const searchParams = useSearchParams();
    const initialPage = Number(searchParams.get('page')) || 1;
    const [page, setPage] = useState(initialPage);
    const router = useRouter();
    const [isPending, startTransition] = useTransition();

    useEffect(() => {
        // 用startTransition包裹导航,让React跟踪加载过程
        startTransition(() => {
            router.push(`/orders?page=${page}`);
        });
    },[page]);

    return (
        <div className="mt-8">
            {/* 加载状态提示 */}
            {isPending && (
                <div className="mb-4 text-center text-blue-600">
                    加载中,请稍候...
                </div>
            )}
            <Pagination
                isCompact
                showControls
                showShadow
                color="primary"
                page={page}
                total={pages}
                onChange={(newPage) => setPage(newPage)}
                isDisabled={isPending} // 加载时禁用分页,防止重复点击
            />
        </div>
    );
}

方案2:结合Suspense实现组件级加载状态

将数据获取逻辑拆分到独立的服务器组件,并用Suspense包裹,在数据加载时显示自定义fallback(可复用loading.js的内容):

  1. 创建独立的订单列表服务器组件:
// orders/OrdersList.js
import CTable from './dataTable';

export default async function OrdersList({ page }) {
  const orders = await getData(page);
  return <CTable data={orders} />;
}
  1. 修改page.js,添加Suspense边界:
// orders/page.js
import { Suspense } from 'react';
import OrdersList from './OrdersList';
import Pagi from './Pagi';

export default async function page({ searchParams }) {
  const currentPage = searchParams.page || 1;
  
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
        <Suspense fallback={
          {/* 可直接复用loading.js的加载UI,或自定义样式 */}
          <div className="flex items-center justify-center h-64">
            <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
          </div>
        }>
          <OrdersList page={currentPage} />
        </Suspense>
      </div>
      <Pagi pages={10}/>
    </main>
  )
}

补充说明

  • 方案1适合快速添加分页专属的加载提示,用户体验更聚焦;
  • 方案2适合需要统一组件级加载状态的场景,可复用加载UI;
  • 若希望完全复用loading.js的页面级加载效果,可尝试router.refresh(),但该方法会触发服务器组件全量刷新,体验接近硬刷新,需谨慎使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:17:03