Next.js 13中如何检测404页面?解决未登录用户访问限制问题
在Next.js 13中检测404页面并调整Firebase认证重定向逻辑
你当前的Firebase认证重定向逻辑会强制未登录用户跳转到登录页,导致他们无法访问404页面。可以通过以下两种方式实现404页面检测,调整重定向规则:
方法一:利用React Context标记404状态(推荐,支持所有404场景)
这种方式能覆盖静态、动态路由导致的所有404情况,通过Context在not-found.tsx中标记当前页面状态,再在认证逻辑中读取该状态跳过重定向。
- 创建NotFound状态Context
// app/auth-context.tsx 'use client'; import { createContext, useContext, useState, ReactNode } from 'react'; const NotFoundContext = createContext<{ isNotFound: boolean; setIsNotFound: (value: boolean) => void }>({ isNotFound: false, setIsNotFound: () => {}, }); export function NotFoundProvider({ children }: { children: ReactNode }) { const [isNotFound, setIsNotFound] = useState(false); return ( <NotFoundContext.Provider value={{ isNotFound, setIsNotFound }}> {children} </NotFoundContext.Provider> ); } export function useNotFound() { return useContext(NotFoundContext); }
- 在根布局中挂载Provider
// app/layout.tsx import { NotFoundProvider } from './auth-context'; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="zh-CN"> <body> <NotFoundProvider>{children}</NotFoundProvider> </body> </html> ); }
- 在
not-found.tsx中设置404状态
// app/not-found.tsx 'use client'; import { useNotFound } from './auth-context'; import { useEffect } from 'react'; export default function NotFound() { const { setIsNotFound } = useNotFound(); useEffect(() => { setIsNotFound(true); // 页面卸载时重置状态 return () => setIsNotFound(false); }, [setIsNotFound]); return ( <div> <h1>404 - 页面不存在</h1> </div> ); }
- 修改认证重定向逻辑
'use client'; import { useRouter, usePathname } from 'next/navigation'; import { useNotFound } from './auth-context'; import { auth } from './firebase-config'; import { onAuthStateChanged } from 'firebase/auth'; import { useEffect } from 'react'; export default function AuthRedirect() { const router = useRouter(); const path = usePathname(); const { isNotFound } = useNotFound(); useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { // 已登录时,若在登录页则跳转首页 if (path === "/login") { router.push("/"); } } else { // 未登录时,仅当不是登录页且不是404页时才跳转登录页 if (path !== "/login" && !isNotFound) { router.push("/login"); } } }); return unsubscribe; }, [path, router, isNotFound]); return null; }
方法二:直接匹配404路径(仅适用于静态404页面)
如果你的404页面是固定的/404路径,可以直接在逻辑中判断路径是否为404,但这种方法无法覆盖动态路由导致的404场景:
onAuthStateChanged(auth, (user) => { if (user) { if (path === "/login") { router.push("/"); } } else { // 排除登录页和404路径 if (path !== "/login" && path !== "/404") { router.push("/login"); } } });
内容的提问来源于stack exchange,提问作者Pratik Dev
相关产品推荐
相关产品推荐

