Next.js中如何在_app.tsx基于用户角色权限实现路由重定向
问题原因
ReferenceError: window is not defined是因为Next.js默认会在服务端执行_app.tsx的渲染逻辑,服务端不存在window、localStorage等浏览器专属API,直接调用就会抛出该错误。- 直接在组件顶层调用跳转逻辑不符合React渲染规则,在服务端渲染阶段也无法执行路由跳转操作。
解决方案
将权限判断和跳转逻辑放到仅在客户端执行的useEffect钩子中,同时增加加载状态避免闪屏,示例代码如下:
import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; // 注意提前定义User类型 type User = { // 你的User字段定义 role: string; } const App: React.FC<{ Component: React.FC; pageProps: Record<string, any>; }> = ({ Component, pageProps }) => { const router = useRouter(); // 加载状态,避免跳转前闪显无权页面 const [authLoading, setAuthLoading] = useState(true); const [isAllowed, setIsAllowed] = useState(false); useEffect(() => { // 仅客户端执行,不会触发服务端报错 const user = JSON.parse(localStorage.getItem('user') ?? 'null') as User | null; const allowed = useRouteProvider(router.pathname, user?.role); setIsAllowed(allowed); if (!allowed) { // replace替代push,避免用户后退回到无权路径 router.replace('/').finally(() => setAuthLoading(false)); return; } setAuthLoading(false); }, [router.pathname]); if (authLoading) { // 可替换为你的项目全局Loading组件 return <div>加载中...</div>; } if (!isAllowed) return null; return <Component {...pageProps} />; }; export default App;
补充说明
- 如果你的项目是Next.js 12+版本,更推荐使用Next.js中间件做全局权限拦截,逻辑更统一,也不会出现客户端闪屏问题。
- 如果部分页面不需要权限校验,可以在
useRouteProvider逻辑中增加路由白名单判断,避免误拦截。
内容的提问来源于stack exchange,提问作者Loudrous
相关产品推荐
相关产品推荐

