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>
Describe the bug
After upgrading
@tanstack/vue-formfrom1.31.0to1.32.0, thestateobject exposed by<form.Field v-slot="{ field, state }">appears to stop updating in Vue templates.In
1.31.0, binding inputs and validation UI tostate.value/state.metaworks as expected. In1.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.Fieldscoped slot.Minimal reproduction
Using Vue 3 and
@tanstack/vue-form@1.32.0:Expected behavior
state.valueandstate.metain theform.Fieldslot should update afterfield.handleChange,form.reset, andform.setFieldMeta, as they did in1.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-formback to1.31.0fixes 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.0useduseStore(fieldApi.store, (state) => state)and the VueFieldcomponent passedfieldApi.state.valueinto the slot at render time. In1.32.0,useFieldbuilds a computedfieldState, but returnsstate: fieldState.value, and theFieldcomponent passes thatstatedirectly 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
@tanstack/vue-form1.31.01.32.03.5.346.0.3Additional notes
The affected usage follows the documented Vue scoped slot pattern: