NextJs13旧页面结构下supabase.auth.onAuthStateChange不触发
解决Supabase auth.onAuthStateChange在Next.js 13旧Page结构中不触发的问题
问题根源分析
你的代码里存在两个核心问题导致监听器无法正常工作:
- useEffect未设置依赖数组且无清理逻辑:没有依赖数组的useEffect会在组件每次渲染时重复注册监听器,既可能导致逻辑冲突,还会造成内存泄漏;同时Supabase的状态监听器需要手动卸载,否则组件销毁后回调仍可能执行。
- 监听器注册逻辑不严谨:缺少对监听器的清理操作,且未确保Supabase实例稳定唯一。
修改后的完整代码
export default function App({ Component, pageProps, router }) { const [supabase] = useState(() => createBrowserSupabaseClient()) // 同步session状态,可选但推荐 const [session, setSession] = useState(pageProps.initialSession) useEffect(() => { // 注册auth状态变化监听器,获取订阅实例用于后续卸载 const { data: listener } = supabase.auth.onAuthStateChange((event, newSession) => { setSession(newSession) if (event === 'SIGNED_IN') { console.log('已登录') // 替换成你的toast提示逻辑,比如:toast.success('登录成功!') } if (event === 'SIGNED_OUT') { console.log('已登出') // 替换成你的toast提示逻辑,比如:toast.info('已退出登录') } }) // 组件卸载时移除监听器,避免内存泄漏 return () => listener.subscription.unsubscribe() }, [supabase]) // 仅当supabase实例变化时重新注册监听器 return ( <SessionContextProvider supabaseClient={supabase} initialSession={session} > <div className="fixed inset-0 flex justify-center sm:px-8"> <div className="flex w-full max-w-7xl lg:px-8"> <div className="w-full bg-white ring-1 ring-gray-100 dark:bg-zinc-900 dark:ring-zinc-300/20" /> </div> </div> <div className="relative"> <Header /> <main> <Component previousPathname={previousPathname} {...pageProps} /> </main> <Footer /> </div> <Analytics /> <Toaster /> </SessionContextProvider> ) }
额外排查要点
- 确认登录/登出操作使用Supabase官方提供的方法(如
signInWithPassword、signOut),手动修改session不会触发状态监听。 - 检查Supabase客户端与SessionContext的版本兼容性,版本不匹配可能导致状态同步异常。
- 确保
createBrowserSupabaseClient仅在客户端执行,你的代码中用useState初始化的方式是正确的,避免在SSR阶段运行。
内容的提问来源于stack exchange,提问作者James Wong
相关产品推荐
相关产品推荐

