Svelte项目中ActionData导入失败及form变量获取问题
问题原因及解决办法
核心问题所在
fail()函数用错了地方:fail()是SvelteKit服务器端Action的专属API,你把它写在前端组件的loginWithEmail函数里完全不会生效——前端没有SvelteKit的Action上下文,所以form变量始终是null。ActionData类型不存在的原因:ActionData是SvelteKit自动生成的类型,只有当你在对应页面的+page.server.ts里定义了服务器Action时,才会出现在./$types里。你现在没有服务器Action,自然找不到这个导出。
两种解决路径
路径一:改用SvelteKit服务器Action(推荐,符合框架规范)
- 在
/login目录下创建+page.server.ts,把登录逻辑移到服务器端:
import { fail, redirect } from '@sveltejs/kit'; import { signInWithEmailAndPassword } from 'firebase/auth'; import { auth } from '$lib/firebase'; // 替换成你Firebase auth实例的实际导出路径 export const actions = { default: async ({ request }) => { const formData = await request.formData(); const email = formData.get('email') as string; const password = formData.get('password') as string; try { await signInWithEmailAndPassword(auth, email, password); // 服务器端操作session需用event.locals,建议先在hooks.ts配置同步逻辑 throw redirect(303, '/'); } catch (error: any) { const code = error.code; if (!code) { return fail(400, { email, unknown: true }); } switch (code) { case 'auth/wrong-password': return fail(400, { email, wrongPassword: true }); case 'auth/missing-password': return fail(400, { email, missingPassword: true }); case 'auth/invalid-email': return fail(400, { email, invalidEmail: true }); default: return fail(400, { email, unknown: true }); } } } };
- 修改
+page.svelte的表单和逻辑:- 不需要自定义
loginWithEmail函数,表单直接用method="POST"(服务器Action默认接收POST请求) - 此时
./$types会自动生成ActionData类型,可正常导入使用:
- 不需要自定义
<script lang="ts"> import type { ActionData } from './$types'; export let form: ActionData; </script> <form method="POST"> {#if form?.wrongPassword}<p class="error">Wrong password.</p>{/if} {#if form?.missingPassword}<p class="error">Missing password.</p>{/if} {#if form?.invalidEmail}<p class="error">Malformed email.</p>{/if} {#if form?.unknown}<p class="error">Authentication error.</p>{/if} <input name="email" type="text" placeholder="Email" value={form?.email ?? ''} /> <input name="password" type="password" placeholder="Password" /> <button type="submit">Login</button> </form>
- 注意:表单输入需加
name属性,服务器端才能通过formData获取值;value={form?.email ?? ''}用于错误时预填用户输入的邮箱。
路径二:前端自行处理错误状态(不使用服务器Action)
如果坚持在前端处理登录逻辑,不要用SvelteKit的form变量,自己定义前端错误状态:
<script lang="ts"> let email = ''; let password = ''; let error: { wrongPassword?: boolean; missingPassword?: boolean; invalidEmail?: boolean; unknown?: boolean } | null = null; async function loginWithEmail() { error = null; try { const result = await signInWithEmailAndPassword(auth, email, password); const { user } = result; await session.set({ loggedIn: true, user: { displayName: user?.displayName, email: user?.email, photoURL: user?.photoURL, uid: user?.uid } }); goto('/'); } catch (err: any) { const code = err.code; if (!code) { error = { unknown: true }; return; } switch (code) { case 'auth/wrong-password': error = { wrongPassword: true }; break; case 'auth/missing-password': error = { missingPassword: true }; break; case 'auth/invalid-email': error = { invalidEmail: true }; break; default: error = { unknown: true }; break; } } } </script> <form on:submit|preventDefault={loginWithEmail}> {#if error?.wrongPassword}<p class="error">Wrong password.</p>{/if} {#if error?.missingPassword}<p class="error">Missing password.</p>{/if} {#if error?.invalidEmail}<p class="error">Malformed email.</p>{/if} {#if error?.unknown}<p class="error">Authentication error.</p>{/if} <input bind:value={email} type="text" placeholder="Email" /> <input bind:value={password} type="password" placeholder="Password" /> <button type="submit">Login</button> </form>
内容的提问来源于stack exchange,提问作者Crag
相关产品推荐
相关产品推荐

