SvelteKit store服务端有值,浏览器端返回undefined
问题原因及解决方案
核心问题
SvelteKit中服务端与客户端的Store实例完全隔离:你在+page.server.ts里设置的userSession值只存在于当前服务端请求的上下文里,不会自动同步到客户端。服务端渲染组件时,用的是当前请求的服务端Store实例,所以能打印出值;但客户端页面激活(hydrate)后,用的是浏览器全新的Store实例,初始值就是undefined,自然读不到服务端设置的内容。
正确实现方式
要让客户端能拿到用户会话数据,需要把数据持久化或传递到客户端,这里推荐两种常用方案:
方案1:通过Cookie传递+客户端Store初始化
- 服务端登录时把用户信息存入Cookie(生产环境建议加密处理)
修改login/+page.server.ts:
import type { Actions } from './$types'; import { redirect } from '@sveltejs/kit'; import type { User } from './types'; export const actions: Actions = { default: async ({ cookies }) => { const user: User = {"username": "test", "email": "email@test.com"}; // 写入Cookie,允许客户端读取(httpOnly设为false) cookies.set('user-session', JSON.stringify(user), { path: '/', httpOnly: false, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', maxAge: 60 * 60 * 24 * 7 // 有效期7天 }); throw redirect(303, '/'); } };
- 改造Store,客户端初始化时从Cookie读取数据
修改lib/stores.ts:
import { writable } from 'svelte/store'; import type { User } from '../login/types'; function createUserSession() { let initialValue: User | undefined; // 仅在客户端环境读取Cookie if (typeof window !== 'undefined') { const cookie = document.cookie .split('; ') .find(row => row.startsWith('user-session=')) ?.split('=')[1]; if (cookie) { initialValue = JSON.parse(decodeURIComponent(cookie)); } } const { subscribe, set, update } = writable(initialValue); return { subscribe, set, update, // 新增登出方法,清除Cookie和Store值 logout: () => { set(undefined); if (typeof window !== 'undefined') { document.cookie = 'user-session=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'; } } }; } export const userSession = createUserSession();
方案2:利用SvelteKit Locals+Page Data传递
- 配置
hooks.server.ts,从Cookie读取用户信息存入Locals
import type { Handle } from '@sveltejs/kit'; import type { User } from './login/types'; export const handle: Handle = async ({ event, resolve }) => { const sessionCookie = event.cookies.get('user-session'); event.locals.user = sessionCookie ? JSON.parse(sessionCookie) as User : undefined; const response = await resolve(event); return response; };
- 在根布局的服务端Load函数中传递用户数据
+layout.server.ts:
import type { LayoutServerLoad } from './$types'; export const load: LayoutServerLoad = async ({ locals }) => { return { user: locals.user }; };
- 在根布局组件中初始化Store
+layout.svelte:
<script lang="ts"> import { userSession } from '$lib/stores'; export let data; // 把服务端传递的用户数据同步到客户端Store $userSession = data.user; </script> <slot />
验证
修改后,客户端组件中访问$userSession就能正常拿到用户数据,服务端和客户端控制台都会输出正确的值。
内容的提问来源于stack exchange,提问作者fullstacknoob
相关产品推荐
相关产品推荐

