Next JS 13 App目录下进度条实现失败,求可行解决方案
Next.js 13 App Router 进度条实现解决方案
你遇到的核心问题是:Pages Router 时代的 next/router API 在 App Router 中不再适用,App Router 采用了全新的客户端路由钩子,旧的路由事件监听逻辑自然失效。以下是两种可行的实现方案:
方案一:使用适配 App Router 的第三方进度条库
确保安装最新版的 nextjs-progressbar(已支持 App Router),直接在客户端根布局中引入即可:
"use client"; import { ChakraProvider } from "@chakra-ui/react"; import "../styles/globals.css"; import NextNProgress from "nextjs-progressbar"; import { wrapper } from "../store"; function RootLayout({ children }) { return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ChakraProvider> <NextNProgress color="red" height={1} /> {children} </ChakraProvider> </body> </html> ); } export default wrapper.withRedux(RootLayout);
方案二:基于 Chakra UI 自定义实现
利用 App Router 提供的 useRouter 钩子的 isPending 状态,结合 Chakra UI Progress 组件实现:
基础版(静态进度)
"use client"; import { ChakraProvider, Progress } from "@chakra-ui/react"; import "../styles/globals.css"; import { wrapper } from "../store"; import { useRouter } from "next/navigation"; function RootLayout({ children }) { const router = useRouter(); // isPending 自动标识路由跳转状态 const isLoading = router.isPending; return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ChakraProvider> {isLoading && <Progress value={80} height={1} animate={true} />} {children} </ChakraProvider> </body> </html> ); } export default wrapper.withRedux(RootLayout);
进阶版(动态进度动画)
如果需要模拟从 0 到 100 的加载动画效果:
"use client"; import { ChakraProvider, Progress } from "@chakra-ui/react"; import "../styles/globals.css"; import { wrapper } from "../store"; import { useRouter } from "next/navigation"; import { useState, useEffect } from "react"; function RootLayout({ children }) { const router = useRouter(); const [progress, setProgress] = useState(0); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (router.isPending) { setIsLoading(true); // 每隔200ms递增进度,最多到90% const interval = setInterval(() => { setProgress(prev => prev >= 90 ? prev : prev + 10); }, 200); return () => clearInterval(interval); } else { // 跳转完成后直接拉满进度,延迟隐藏 setProgress(100); const timeout = setTimeout(() => { setIsLoading(false); setProgress(0); }, 300); return () => clearTimeout(timeout); } }, [router.isPending]); return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ChakraProvider> {isLoading && <Progress value={progress} height={1} animate={true} />} {children} </ChakraProvider> </body> </html> ); } export default wrapper.withRedux(RootLayout);
关键注意事项
- 所有路由相关逻辑必须在客户端组件中编写(添加
"use client"指令),服务器组件无法访问客户端路由钩子。 - 彻底替换
next/router为next/navigation的useRouter,App Router 不再支持旧的路由事件监听模式。 - 使用第三方库时,务必确认其版本适配 App Router,避免使用仅支持 Pages Router 的老旧版本。
内容的提问来源于stack exchange,提问作者Mohammed Bekele
相关产品推荐
相关产品推荐

