SvelteKit集成Firestore页面重载时崩溃或无数据问题求助
问题解决:SvelteKit页面重载/HMR时Firestore数据加载失败或崩溃
问题根源
- 首页重载无数据:
getAuth().currentUser在页面初始化(尤其是重载)时可能未完成认证初始化,直接取值会得到undefined,导致load函数跳过Firestore数据获取,返回undefined,页面执行Object.values(data)时因空值崩溃。 - Profile页面重载500:根布局的Auth状态处理放在
onMount中,仅在客户端挂载后执行,重载页面时userStore初始为空,直接访问$user.displayName等属性会因$user为undefined抛出错误。 - CodeSandbox能加载成功是因为缓存了Auth状态,本地重载时Auth状态需要重新初始化,存在延迟。
解决方案
1. 移到根布局load函数处理Auth认证(替代onMount)
将Auth状态获取放在+layout.ts的load函数中,确保页面加载前完成认证校验,避免客户端挂载延迟问题:
// src/routes/+layout.ts import { getAuth, onAuthStateChanged } from "firebase/auth"; import { redirect } from "@sveltejs/kit"; import { userStore } from "$lib/stores"; export const load = async () => { const auth = getAuth(); // 用Promise包裹Auth状态监听,等待初始化完成 const user = await new Promise((resolve) => { const unsubscribe = onAuthStateChanged(auth, (user) => { resolve(user); unsubscribe(); }); }); if (!user) { throw redirect(307, "/login"); } userStore.set({ uid: user.uid, displayName: user.displayName, email: user.email }); return { user }; };
修改根布局+layout.svelte,移除onMount的Auth逻辑,同步load返回的用户数据:
<!-- src/routes/+layout.svelte --> <script> import { userStore } from "$lib/stores"; export let data; // 确保store初始状态与load返回的用户数据一致 $user = data.user; </script> <!-- 你的布局内容 -->
2. 修复首页load函数,确保拿到用户后再获取数据
依赖根布局load返回的用户数据,避免直接取未初始化的currentUser:
// src/routes/+page.ts import { doc, getDoc } from "firebase/firestore"; import { db } from "$lib/firebase"; import { userData } from "$lib/stores"; export const load = async ({ parent }) => { // 从根布局获取已认证的用户数据 const { user } = await parent(); const uid = user.uid; const docRef = doc(db, "ammo", uid); const docSnap = await getDoc(docRef); // 空值兜底,避免返回undefined const ammoData = docSnap.data()?.ammo || []; userData.set(ammoData); return { ammo: ammoData }; };
3. 首页页面增加空值处理,避免崩溃
修改+page.svelte,确保数据为空时不会抛出错误:
<!-- src/routes/+page.svelte --> <script lang="ts"> interface userAmmo { name: string; count: number; grain: number; type: string; } export let data; let parsedData: userAmmo[] = []; // 仅当数据存在时解析 $: if (data?.ammo) { parsedData = Object.values(data.ammo); } </script> {#if parsedData.length === 0} <p>No ammo data found.</p> {:else} <!-- 你的数据渲染逻辑 --> {/if}
4. Profile页面增加空值兜底,避免500错误
给$user设置空对象兜底,防止访问不存在的属性:
<!-- src/routes/profile/+page.svelte --> <script> import { userStore } from "$lib/stores"; $: user = $user || {}; $: displayName = user.displayName || 'No User'; $: uid = user.uid || 'Unavailable'; $: email = user.email || 'Unavailable'; console.log(user); </script>
内容的提问来源于stack exchange,提问作者Thakrisp
相关产品推荐
相关产品推荐

