Svelte 5中hooks.client.ts如何用$state?Pocketbase认证赋值报错求助
Pocketbase + Svelte 5 认证实现问题解决方案
问题描述
我正在结合Pocketbase与Svelte 5实现认证功能,参考相关仓库的hooks.client.ts实现后,遇到两个问题:
- 在
$lib/stores/user.svelte.ts中定义$state变量后,在+layout.svelte中直接赋值时VSCode提示错误:Cannot assign to import svelte(constant_assignment)。 - 不清楚如何在
hooks.client.ts中使用$state。
相关代码:
// src/lib/stores/user.svelte.ts import { type AuthModel } from 'pocketbase' export let currentUser: AuthModel | null = $state(null)
// src/+layout.svelte <script lang="ts"> import { pb } from '$lib/pocketbase' import { currentUser } from '$lib/stores/user.svelte' let { children } = $props() pb.authStore.loadFromCookie(document.cookie) pb.authStore.onChange(() => { currentUser = pb.authStore.model document.cookie = pb.authStore.exportToCookie({ httpOnly: false }) }, true) </script> {@render children()}
问题1:解决Cannot assign to import错误
Svelte 5中从.svelte.ts导出的$state变量默认是只读的,直接赋值会触发常量赋值错误,可通过以下两种方案解决:
方案A:封装状态与修改函数
修改user.svelte.ts,将状态私有化,导出只读状态和修改函数:
// src/lib/stores/user.svelte.ts import { type AuthModel } from 'pocketbase' // 内部私有状态 let _currentUser: AuthModel | null = $state(null) // 导出只读的派生状态 export const currentUser = $derived(_currentUser) // 导出修改状态的函数 export const setCurrentUser = (user: AuthModel | null) => { _currentUser = user }
在+layout.svelte中调用修改函数更新状态:
// src/+layout.svelte <script lang="ts"> import { pb } from '$lib/pocketbase' import { currentUser, setCurrentUser } from '$lib/stores/user.svelte' let { children } = $props() pb.authStore.loadFromCookie(document.cookie) pb.authStore.onChange(() => { setCurrentUser(pb.authStore.model) document.cookie = pb.authStore.exportToCookie({ httpOnly: false }) }, true) </script> {@render children()}
方案B:使用可写状态引用(Svelte 5最新语法)
如果使用Svelte 5最新版本,也可以通过函数封装可写状态,避免直接暴露可写变量:
// src/lib/stores/user.svelte.ts import { type AuthModel } from 'pocketbase' export function createUserStore() { let currentUser: AuthModel | null = $state(null) return { get currentUser() { return currentUser }, set currentUser(user: AuthModel | null) { currentUser = user } } }
在组件中实例化后使用:
// src/+layout.svelte <script lang="ts"> import { pb } from '$lib/pocketbase' import { createUserStore } from '$lib/stores/user.svelte' const userStore = createUserStore() let { children } = $props() pb.authStore.loadFromCookie(document.cookie) pb.authStore.onChange(() => { userStore.currentUser = pb.authStore.model document.cookie = pb.authStore.exportToCookie({ httpOnly: false }) }, true) </script> {@render children()}
问题2:在hooks.client.ts中使用状态管理
hooks.client.ts是普通.ts文件,无法直接使用$state语法,可通过以下两种方案实现状态同步:
方案A:使用createSignal底层API
Svelte 5提供的createSignal可以在普通.ts文件中使用,替代$state实现状态管理:
// src/lib/stores/user.ts import { type AuthModel } from 'pocketbase' import { createSignal } from 'svelte' // 创建信号,返回可读函数和可写函数 export const [currentUser, setCurrentUser] = createSignal<AuthModel | null>(null)
在hooks.client.ts中直接调用更新函数:
// src/hooks.client.ts import { pb } from '$lib/pocketbase' import { setCurrentUser } from '$lib/stores/user' pb.authStore.loadFromCookie(document.cookie) pb.authStore.onChange(() => { setCurrentUser(pb.authStore.model) document.cookie = pb.authStore.exportToCookie({ httpOnly: false }) }, true)
组件中可通过$currentUser订阅状态变化。
方案B:通过自定义事件同步状态
如果坚持使用.svelte.ts的$state,可以在hooks.client.ts中触发自定义事件,让组件监听并更新状态:
// src/hooks.client.ts import { pb } from '$lib/pocketbase' pb.authStore.loadFromCookie(document.cookie) pb.authStore.onChange(() => { document.cookie = pb.authStore.exportToCookie({ httpOnly: false }) // 触发自定义auth变更事件 window.dispatchEvent(new CustomEvent('auth-change', { detail: pb.authStore.model })) }, true)
在+layout.svelte中监听事件更新状态:
// src/+layout.svelte <script lang="ts"> import { pb } from '$lib/pocketbase' import { setCurrentUser } from '$lib/stores/user.svelte' let { children } = $props() // 初始化加载状态 setCurrentUser(pb.authStore.model) // 监听自定义事件更新状态 window.addEventListener('auth-change', (e) => { setCurrentUser((e as CustomEvent).detail) }) </script> {@render children()}
内容的提问来源于stack exchange,提问作者Nikolay Dyankov
相关产品推荐
相关产品推荐

