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

SvelteKit集成Firestore页面重载时崩溃或无数据问题求助

问题解决:SvelteKit页面重载/HMR时Firestore数据加载失败或崩溃

问题根源

  1. 首页重载无数据:getAuth().currentUser在页面初始化(尤其是重载)时可能未完成认证初始化,直接取值会得到undefined,导致load函数跳过Firestore数据获取,返回undefined,页面执行Object.values(data)时因空值崩溃。
  2. Profile页面重载500:根布局的Auth状态处理放在onMount中,仅在客户端挂载后执行,重载页面时userStore初始为空,直接访问$user.displayName等属性会因$user为undefined抛出错误。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 00:35:19