Next.js使用Supabase自定义Hook实现受保护路由时误跳转问题问询
问题根因
你当前遇到的不必要跳转是三个核心原因导致的:
- 自定义
useUser钩子已提供userLoaded状态标记用户信息是否加载完成,你未使用该标记做前置判断,直接将初始化阶段的nullsession值作为了跳转依据。 - 代码中使用了未清理的
setInterval,不仅会重复触发判断,还会导致内存泄漏。 - 额外问题:你的
useUser钩子中userLoaded状态仅在存在登录用户时才会设为true,未登录场景下该状态永远为false,导致跳转逻辑无法正常触发。
修复步骤
1. 先修正useUser钩子的状态逻辑
修改UserContextProvider中监听user变化的useEffect逻辑,保证无论用户是否登录,状态加载完成后都会将userLoaded设为true:
useEffect(() => { setUserLoaded(false); if (user) { Promise.allSettled([getUserDetails(), getSubscription()]).then( (results) => { setUserDetails(results[0].value?.data); setSubscription(results[1].value?.data); setUserLoaded(true); } ); } else { // 无登录用户时也标记加载完成 setUserLoaded(true); } }, [user]);
2. 修复页面跳转逻辑
删掉无用的setInterval,增加加载态占位,仅在用户状态加载完成后再做跳转判断:
// 注意组件名首字母要大写,符合React组件命名规范 const Analytics = () => { const { userLoaded, session } = useUser(); const router = useRouter(); useEffect(() => { // 仅用户状态加载完成后再判断是否跳转 if (userLoaded && !session) { // 这里可自行确认跳转目标是否正确,若未登录应该跳转登录页可替换为对应路由 router.replace("/admindashboard"); } }, [userLoaded, session, router]); // 加载过程中展示占位UI,避免页面内容闪现 if (!userLoaded) return <div>加载中...</div>; return ( <> <Dashboard /> <p>Coming soon</p> </> ); }; export default Analytics;
可选优化:封装通用受保护路由
如果有多个页面需要做登录校验,可以封装通用的路由守卫组件,避免每个页面重复写判断逻辑:
import { useUser } from './useUser'; import { useRouter } from 'next/router'; export const ProtectedRoute = ({ children }) => { const { userLoaded, session } = useUser(); const router = useRouter(); useEffect(() => { if (userLoaded && !session) { router.replace('/login'); } }, [userLoaded, session, router]); if (!userLoaded) return <div>加载中...</div>; return session ? children : null; };
使用时直接包裹需要保护的页面即可:
// 示例:在_app.js中给指定页面加校验 import { ProtectedRoute } from './components/ProtectedRoute'; function MyApp({ Component, pageProps }) { // 给需要登录的页面加保护,比如analytics页 if (Component.requireAuth) { return ( <ProtectedRoute> <Component {...pageProps} /> </ProtectedRoute> ); } return <Component {...pageProps} />; } // 在需要保护的页面加标记 Analytics.requireAuth = true;
内容的提问来源于stack exchange,提问作者KeoooDev
相关产品推荐
相关产品推荐

