父组件调用子组件异步登录验证函数失效问题求助
问题分析与解决方案
核心问题排查
- 变量名冲突:你导入了
userstore,但又在isLogged函数里声明了同名局部变量const user = supabase.auth.user();,导致后续user.set(session.user)是对普通用户对象调用store的set方法,完全无效,且user.id的取值也会出错。 - 指令使用不当:用
use:isLogged指令绑定到<p>元素执行登录检查,指令依赖元素挂载触发,当组件作为子组件引入时,元素挂载时机可能和组件初始化不同步,导致逻辑不执行或异常。 - 重复监听内存泄漏:每次组件挂载都注册
supabase.auth.onAuthStateChange监听,未在组件卸载时取消,会造成重复监听和内存泄漏。 - 逻辑反向:查询到用户数据(
data存在)时跳转到登录页,这与登录状态检查的预期逻辑相反,应该是未查询到用户或出错时才跳转。
修正后的代码
<script> import { goto } from '$app/navigation'; import { onMount, onDestroy } from 'svelte'; import { user } from '../sessionStore'; import { supabase } from '../supabaseClient'; let loading = false; let authListener = null; async function checkAuthStatus() { try { loading = true; // 避免变量名冲突,改用currentUser指代当前用户对象 const currentUser = supabase.auth.user(); if (!currentUser) { goto('/signin'); return; } // 更新全局user store user.set(currentUser); let { data, error, status } = await supabase .from('users') .select('*') .eq('id', currentUser.id) .single(); if (error && status !== 406) throw error; // 逻辑修正:仅当数据库中无用户数据时跳转登录页 if (!data) { goto('/signin'); } } catch (error) { console.error('登录状态检查失败:', error); goto('/signin'); } finally { loading = false; } } onMount(async () => { // 组件挂载时立即执行登录状态检查 await checkAuthStatus(); // 注册auth状态变化监听,保存监听函数用于卸载时取消 authListener = supabase.auth.onAuthStateChange((_, session) => { if (session?.user) { user.set(session.user); } else { goto('/signin'); } }); }); onDestroy(() => { // 组件卸载时取消监听,防止内存泄漏 if (authListener) { authListener.unsubscribe(); } }); </script> {#if loading} <p>加载中...</p> {/if}
关键修正说明
- 变量名区分:将局部用户变量改为
currentUser,避免覆盖导入的userstore,确保store的set方法能正确调用。 - 改用生命周期钩子:用
onMount执行初始化登录检查,确保组件挂载时就触发逻辑,不受元素挂载的影响,适配子组件场景。 - 清理监听:用
onDestroy取消onAuthStateChange的监听,防止重复监听和内存泄漏。 - 修正逻辑方向:只有当用户不存在或数据库查询不到用户数据时,才跳转到登录页,符合登录状态检查的预期。
- 加载状态提示:添加加载状态的UI反馈,提升用户体验。
内容的提问来源于stack exchange,提问作者equi
相关产品推荐
相关产品推荐

