Skip to content

Vue: Field slot state stops updating in 1.32.0 #2191

@anguiao

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions