有没有办法为 SvelteKit 中的页面表单存储添加类型安全?

问题描述 投票:0回答:1

我将 HTML 分成两个文件,

+page.svelte
Role.svelte
。这样它更干净、更易于维护,因为我将来会在
+page.svelte
中添加更多精简文件。
Role.svelte
包含表格。

我读过,因为

form
仅传递给
+page.svelte
而不是传递给任何组件,所以我应该在
let form: ActionData
上单独使用
Role.svelte
,而不是在
$page.form
中使用
Role.svelte
。我遇到的一个问题是
$page.form
没有类型安全和类型推断,与
ActionData
不同。如何在不牺牲文件组织的情况下使
$page.form
具有与
let form: ActionData
相同的推论?

(这是代码):

Role.svelte

<script lang="ts">
  import { enhance } from "$app/forms";
  import { page } from "$app/stores";
  import type { ActionData } from "./$types";
  let form: ActionData = $page.form // tried, returned undefined
  form = form // did not change anything
  let userRoles = ["admin", "student"];
</script>

<form method="post" action="?/role" use:enhance>
  <!-- did not work, had to use $page.form which again has no typing -->
  {#if form?.noSelectedRole}
    <p>{form?.error}</p>
  {/if}

  <p>You are a/an...</p>
  {#each userRoles as userRole}
    <input type="radio" value={userRole} name="role" />
    <label for={userRole}>{userRole}</label>
    <br />
  {/each}

  <slot />
  <!-- For when the school can't be found -->

  <p>What school are you a part of? Type its DepEd school ID.</p>
  <input type="text" name="schoolId" placeholder="School" />
  <br />
  <button type="submit">Check</button>
</form>

+page.svelte

<script lang="ts">
  import { page } from "$app/stores";
  import type { ActionData } from "./$types";
  import Role from "./Role.svelte";
  let form: ActionData = $page.form // did not work
</script>

<Role>
  <p>
    <!-- undefined, had to use $page.form but again, no typing :( -->
    {console.log(form?.noSelectedRole)}
    {#if form?.noSelectedRole}
      Select a role please.
    {/if}
  </p>
</Role>

+page.server.ts

import type { Actions } from "./$types";
import { fail, redirect } from '@sveltejs/kit';

export const actions = {
    role: async ({ request }) => {
        const formData = await request.formData()
        const userRole = formData.get("role") as string
        const schoolId = formData.get("schoolId") as string

        console.log(`role: ${userRole}`)
        console.log(`school id: ${schoolId}`)

        if (typeof userRole !== "string" ||
            userRole == null) {
            console.log("no user role selected")
            return fail(400, {
                noSelectedRole: true,
                error: "Please select a role.",
                data: {...{userRole, schoolId}}
            })
        }
    }
} satisfies Actions;
typescript sveltekit type-safety svelte-store
1个回答
0
投票

您的方向是正确的,但您的代码中存在一些细微的错误。

// <Role.svelte>
import type { ActionData } from "./$types";
let form: ActionData = $page.form

第一次创建组件时,

form
undefined
,因为还没有表单数据。提交表单后
$page.form
发生更改,但您的
form
变量不会更新,因为 SvelteKit 不会重新创建您的
Role
组件,它会重用它

要解决此问题,您需要使

form
变量具有反应性:

// <Role.svelte>
import type { ActionData } from "./$types";
$: form = $page.form as ActionData

您的代码还有另一个问题,这次是在内部

+page.svelte
:

// <+page.svelte>
import type { ActionData } from "./$types";
let form: ActionData = $page.form;

有两件事:你不需要赋值,并且你需要导出变量。应该是这样的:

// <+page.svelte>
import type { ActionData } from "./$types";
export let form: ActionData;
© www.soinside.com 2019 - 2024. All rights reserved.