Skip to content

Vue: Field slot state stops updating in 1.32.0 #2191

Description

@anguiao

Describe the bug

After upgrading @tanstack/vue-form from 1.31.0 to 1.32.0, the state object exposed by <form.Field v-slot="{ field, state }"> appears to stop updating in Vue templates.

In 1.31.0, binding inputs and validation UI to state.value / state.meta works as expected. In 1.32.0, the same code renders stale slot state after updates such as:

  • field.handleChange(...)
  • form.reset(...)
  • form.setFieldMeta(...)

This affects documented usage of the Vue adapter's form.Field scoped slot.

Minimal reproduction

Using Vue 3 and @tanstack/vue-form@1.32.0:

<script setup lang="ts">
import { useForm } from '@tanstack/vue-form'

const form = useForm({
  defaultValues: {
    name: '',
  },
})

function resetName() {
  form.reset({ name: 'Ada' })
}

function setServerError() {
  form.setFieldMeta('name', (meta) => ({
    ...meta,
    errorMap: {
      ...meta.errorMap,
      onServer: 'Name is already taken',
    },
    errorSourceMap: {
      ...meta.errorSourceMap,
      onServer: 'form',
    },
  }))
}
</script>

<template>
  <button type="button" @click="resetName">Reset name</button>
  <button type="button" @click="setServerError">Set server error</button>

  <form.Field name="name" v-slot="{ field, state }">
    <input
      :value="state.value"
      @input="field.handleChange(($event.target as HTMLInputElement).value)"
      @blur="field.handleBlur"
    />

    <p data-testid="value">{{ state.value }}</p>
    <p data-testid="server-error">{{ state.meta.errorMap.onServer }}</p>
  </form.Field>
</template>

Expected behavior

state.value and state.meta in the form.Field slot should update after field.handleChange, form.reset, and form.setFieldMeta, as they did in 1.31.0.

Actual behavior

The template continues to render the initial/default slot state. In a real Vue 3 app, this caused stale input values, missing server validation feedback, and array field rows not rendering after form values were reset or changed. Pinning @tanstack/vue-form back to 1.31.0 fixes the same tests and UI behavior.

Related context

This may be related to #2172, which fixed #2018 by changing adapter re-render behavior for array fields and introduced _arrayVersion.

From a quick source comparison, 1.31.0 used useStore(fieldApi.store, (state) => state) and the Vue Field component passed fieldApi.state.value into the slot at render time. In 1.32.0, useField builds a computed fieldState, but returns state: fieldState.value, and the Field component passes that state directly to the slot. That looks like it may turn the slot state into a snapshot rather than a reactive value for Vue template consumers.

Environment

  • Adapter: @tanstack/vue-form
  • Working version: 1.31.0
  • Failing version: 1.32.0
  • Vue: 3.5.34
  • TypeScript: 6.0.3
  • Runtime observed in Vue 3 + Vite tests and app components

Additional notes

The affected usage follows the documented Vue scoped slot pattern:

<form.Field name="name" v-slot="{ field, state }">
  <input :value="state.value" @input="field.handleChange(...)" />
  <FieldInfo :state="state" />
</form.Field>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions