You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js使用Supabase自定义Hook实现受保护路由时误跳转问题问询

问题根因

你当前遇到的不必要跳转是三个核心原因导致的:

  • 自定义useUser钩子已提供userLoaded状态标记用户信息是否加载完成,你未使用该标记做前置判断,直接将初始化阶段的null session值作为了跳转依据。
  • 代码中使用了未清理的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 09:24:03