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

Svelte Store美元赋值与原生方法的差异及表单提交异常分析

问题分析:SvelteKit表单提交时Store状态未更新的问题

场景与代码

我正在使用SvelteKit与TypeScript构建表单,通过Svelte Store管理用户输入状态并封装到模块中,相关代码如下:

useFormInput.svelte

<script lang="ts" context="module">
  import {writable, get} from "svelte/store"
  type Form = {
    name: string, job: string, home: string, gender: string
  }
  export const useFormInput = () => {
    const form = writable<Form>({
      name: "", job: "", home: "", gender: ""
    })
    const onChange = <T extends string = keyof Form>(key: T, value: T extends keyof Form ? Form[T] : never) => {
      const _form = get(form)
      form.set({
        ..._form, [key]: value
      })
    }

    return {form, onChange}
  }
</script>

useFormSubmit.svelte

<script lang="ts" context="module">
  import {writable} from "svelte/store"
  type Form = {
    name: string, job: string, home: string, gender: string
  }
  type Props = {
    form: Form
  }
  export const useFormSubmit = (props: Props) => {
    const isLoading = writable(false)
    const onSubmit = async () => {
      isLoading.set(true)
      await new Promise((resolve) => {
        setTimeout(() => {
          resolve(null!)
        }, 3000)
      })
      console.log(props.form, "form submitted")
      isLoading.set(false)
    }

    return {onSubmit, isLoading}
  }
</script>

问题描述

useFormInput返回form store对象及使用set方法更新store的onChange函数,useFormSubmit接收store的form值作为参数并返回提交触发函数。填写表单后提交时,控制台显示form store仍为初始空值{name: "", job: "", home: "", gender: ""},但使用美元赋值($form)替代onChange时,表单内容能正常显示。想了解二者是否存在未知差异?


问题根源

你在调用useFormSubmit时,传递的是Store初始化时的快照值,而不是Store对象本身。当后续通过onChange更新Store时,useFormSubmit内部的props.form还是最初传入的那个静态对象,不会自动同步Store的最新状态。

而$form是Svelte的语法糖,它会自动订阅Store的变化:

  • 读取$form时拿到的是Store的最新值
  • 修改$form(比如$form.name = 'xxx')本质上是直接更新Store内部的当前值,同时触发组件和订阅者的更新

解决方法

修改useFormSubmit,让它接收Store对象而非快照值,提交时再获取Store的最新状态:

修改后的useFormSubmit.svelte

<script lang="ts" context="module">
  import {writable, get} from "svelte/store"
  type Form = {
    name: string, job: string, home: string, gender: string
  }
  // 改为接收Store对象类型
  type Props = {
    form: ReturnType<typeof writable<Form>>
  }
  export const useFormSubmit = (props: Props) => {
    const isLoading = writable(false)
    const onSubmit = async () => {
      isLoading.set(true)
      await new Promise((resolve) => {
        setTimeout(() => {
          resolve(null!)
        }, 3000)
      })
      // 提交时获取Store的最新值
      const latestForm = get(props.form)
      console.log(latestForm, "form submitted")
      isLoading.set(false)
    }

    return {onSubmit, isLoading}
  }
</script>

组件中调用方式

在使用的组件里,直接传入Store对象form,而非快照值$form:

const { form, onChange } = useFormInput();
const { onSubmit, isLoading } = useFormSubmit({ form });

补充说明

  • 你自己实现的onChange逻辑本身没有问题,它确实通过set方法正确更新了Store状态
  • 问题核心在于提交时没有从Store中获取最新值,而是依赖了初始化时的静态快照

内容的提问来源于stack exchange,提问作者nw.lee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:02:04