Next.js 13 App目录下nextjs-progressbar无法工作,求实现方法
在Next.js 13 App目录中实现进度条的正确方法
nextjs-progressbar是为Pages Router设计的,依赖旧的路由事件系统,在App Router中无法正常触发。下面提供两种可行的解决方案:
方案一:使用适配App Router的进度条包
推荐使用nextjs-toploader,它专门支持Next.js 13+的App Router:
- 安装依赖
npm install nextjs-toploader # 或 yarn add nextjs-toploader
- 修改根layout组件
将原代码中的NextNProgress替换为NextTopLoader,确保组件带有"use client"指令:
"use client"; import { ChakraProvider } from "@chakra-ui/react"; import "../styles/globals.css"; import NextTopLoader from "nextjs-toploader"; import { wrapper } from "../store"; function RootLayout({ children }) { return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ChakraProvider> <NextTopLoader color="#06373a" /> {children} </ChakraProvider> </body> </html> ); } export default wrapper.withRedux(RootLayout);
方案二:手动实现进度条
如果不想额外安装包,可以基于App Router的路由事件手动实现:
- 创建客户端组件
ProgressBar.jsx
"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; export default function ProgressBar() { const [progress, setProgress] = useState(0); const [isVisible, setIsVisible] = useState(false); const router = useRouter(); useEffect(() => { const startProgress = () => { setIsVisible(true); setProgress(0); const timer = setInterval(() => { setProgress(prev => { if (prev >= 90) { clearInterval(timer); return prev; } return prev + 10; }); }, 100); }; const finishProgress = () => { setProgress(100); setTimeout(() => setIsVisible(false), 300); }; router.events.on("routeChangeStart", startProgress); router.events.on("routeChangeComplete", finishProgress); router.events.on("routeChangeError", finishProgress); return () => { router.events.off("routeChangeStart", startProgress); router.events.off("routeChangeComplete", finishProgress); router.events.off("routeChangeError", finishProgress); }; }, [router]); return isVisible ? ( <div style={{ position: "fixed", top: 0, left: 0, right: 0, height: "3px", backgroundColor: "#06373a", width: `${progress}%`, zIndex: 9999, transition: "width 0.2s ease-out", }} /> ) : null; }
- 在根layout中引入该组件
"use client"; import { ChakraProvider } from "@chakra-ui/react"; import "../styles/globals.css"; import ProgressBar from "./ProgressBar"; import { wrapper } from "../store"; function RootLayout({ children }) { return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ChakraProvider> <ProgressBar /> {children} </ChakraProvider> </body> </html> ); } export default wrapper.withRedux(RootLayout);
内容的提问来源于stack exchange,提问作者mobix
相关产品推荐
相关产品推荐

