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

NextJS 13 App目录下如何实现加载指示器或进度条?

在Next.js 13 App Directory架构下实现客户端路由加载进度条/指示器

问题根源

App Directory中,根目录的loading.tsx仅针对Server Components的SSR/SSG加载生效,而客户端组件页面(如首页、登录/注册页)的路由跳转是在客户端侧完成的,不会触发loading.tsx。旧的next-n-progress失效是因为它依赖Pages Router的路由事件机制,而App Directory使用了新的next/navigation路由API。

解决方案一:手动实现自定义进度条(无依赖)

创建一个客户端组件,通过监听App Directory的路由事件来控制进度条显示:

  1. 创建components/ProgressBar.tsx(必须标记为客户端组件):
'use client';

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';

export default function ProgressBar() {
  const [isLoading, setIsLoading] = useState(false);
  const router = useRouter();

  useEffect(() => {
    // 路由跳转开始时显示进度条
    const handleRouteStart = () => setIsLoading(true);
    // 跳转完成或出错时隐藏
    const handleRouteEnd = () => setIsLoading(false);

    router.events.on('routeChangeStart', handleRouteStart);
    router.events.on('routeChangeComplete', handleRouteEnd);
    router.events.on('routeChangeError', handleRouteEnd);

    // 组件卸载时移除事件监听
    return () => {
      router.events.off('routeChangeStart', handleRouteStart);
      router.events.off('routeChangeComplete', handleRouteEnd);
      router.events.off('routeChangeError', handleRouteEnd);
    };
  }, [router]);

  return (
    <div
      className={`fixed top-0 left-0 right-0 h-1 bg-indigo-600 transition-all duration-500 ease-out ${
        isLoading ? 'w-full' : 'w-0'
      }`}
    />
  );
}
  1. 在根layout.tsx中全局引入:
import ProgressBar from '@/components/ProgressBar';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="zh-CN">
      <body>
        <ProgressBar />
        {children}
      </body>
    </html>
  );
}

解决方案二:适配next-n-progress到App Directory

如果偏好使用next-n-progress,可以通过客户端组件重新封装,适配新的路由事件:

  1. 安装依赖:
npm install nprogress
  1. 创建components/NProgressWrapper.tsx:
'use client';

import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function NProgressWrapper() {
  const router = useRouter();

  useEffect(() => {
    const handleStart = () => NProgress.start();
    const handleEnd = () => NProgress.done();

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleEnd);
    router.events.on('routeChangeError', handleEnd);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleEnd);
      router.events.off('routeChangeError', handleEnd);
    };
  }, [router]);

  return null;
}
  1. 同样在根layout.tsx中引入该组件即可。

解决方案三:适配MUI的CSS-in-JS方案

如果项目使用MUI,可以直接用MUI的LinearProgress组件实现进度条,保持风格统一:

'use client';

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import LinearProgress from '@mui/material/LinearProgress';
import { Box } from '@mui/material';

export default function MUIProgressBar() {
  const [isLoading, setIsLoading] = useState(false);
  const router = useRouter();

  useEffect(() => {
    const handleStart = () => setIsLoading(true);
    const handleEnd = () => setIsLoading(false);

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleEnd);
    router.events.on('routeChangeError', handleEnd);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleEnd);
      router.events.off('routeChangeError', handleEnd);
    };
  }, [router]);

  return isLoading ? (
    <Box sx={{ 
      width: '100%', 
      position: 'fixed', 
      top: 0, 
      left: 0, 
      zIndex: 9999,
      '& .MuiLinearProgress-root': { height: 3 }
    }}>
      <LinearProgress color="primary" />
    </Box>
  ) : null;
}

关键注意事项

  • 所有监听路由事件的组件必须标记为'use client',因为useRouter只能在客户端组件中使用。
  • 根layout.tsx作为Server Component,直接导入客户端组件是允许的,Next.js会自动处理组件边界。
  • 该方案与loading.tsx互补:SSR页面用loading.tsx,客户端路由跳转用进度条,覆盖所有加载场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 21:32:47