Skip to content

Commit bdf7d3e

Browse files
logaretmclaude
andcommitted
fix: resetField respects current reactive initial value (#4827)
When useField receives a reactive ref as initialValue, resetField now reads the current value of that ref instead of the stale value captured at field creation time. This applies to both standalone useField and useField within a useForm context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7d8cc52 commit bdf7d3e

3 files changed

Lines changed: 84 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"vee-validate": patch
3+
---
4+
5+
Fix resetField to use current reactive initial value instead of stale value (#4827)

packages/vee-validate/src/useFieldState.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ export function _useFieldValue<TValue = unknown>(
126126

127127
function resolveInitialValue() {
128128
if (!form) {
129+
// If the original modelValue is a ref, read from it directly to maintain reactivity
130+
if (isRef(modelValue)) {
131+
return modelValue.value as TValue;
132+
}
133+
129134
return unref(modelRef) as TValue;
130135
}
131136

@@ -160,6 +165,15 @@ export function _useFieldValue<TValue = unknown>(
160165
// #3429
161166
const currentValue = resolveModelValue(modelValue, form, initialValue, path);
162167
form.stageInitialValue(unref(path), currentValue, true);
168+
169+
// If the modelValue is a ref, watch it and update the form's initial value when it changes
170+
// This ensures resetField uses the current reactive initial value (#4827)
171+
if (isRef(modelValue)) {
172+
watch(modelValue, newVal => {
173+
form.setFieldInitialValue(unref(path), newVal as any, true);
174+
});
175+
}
176+
163177
// otherwise use a computed setter that triggers the `setFieldValue`
164178
const value = computed<TValue>({
165179
get() {

packages/vee-validate/tests/useField.spec.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,4 +1059,69 @@ describe('useField()', () => {
10591059

10601060
expect(form.values.field).toEqual('test');
10611061
});
1062+
1063+
// #4827
1064+
test('resetField should use current reactive initial value (without form)', async () => {
1065+
let field!: FieldContext;
1066+
const initialValue = ref('before change');
1067+
1068+
mountWithHoc({
1069+
setup() {
1070+
field = useField('field', undefined, { initialValue });
1071+
1072+
return {};
1073+
},
1074+
template: '<div></div>',
1075+
});
1076+
1077+
await flushPromises();
1078+
expect(field.value.value).toBe('before change');
1079+
1080+
// Change the reactive initial value
1081+
initialValue.value = 'after change';
1082+
await flushPromises();
1083+
1084+
// Change the field's current value to something else
1085+
field.value.value = 'some random value';
1086+
await flushPromises();
1087+
1088+
// Reset field should use the new reactive initial value
1089+
field.resetField();
1090+
await flushPromises();
1091+
1092+
expect(field.value.value).toBe('after change');
1093+
});
1094+
1095+
// #4827
1096+
test('resetField should use current reactive initial value (with form)', async () => {
1097+
let field!: FieldContext;
1098+
const initialValue = ref('before change');
1099+
1100+
mountWithHoc({
1101+
setup() {
1102+
useForm();
1103+
field = useField('field', undefined, { initialValue });
1104+
1105+
return {};
1106+
},
1107+
template: '<div></div>',
1108+
});
1109+
1110+
await flushPromises();
1111+
expect(field.value.value).toBe('before change');
1112+
1113+
// Change the reactive initial value
1114+
initialValue.value = 'after change';
1115+
await flushPromises();
1116+
1117+
// Change the field's current value to something else
1118+
field.value.value = 'some random value';
1119+
await flushPromises();
1120+
1121+
// Reset field should use the new reactive initial value
1122+
field.resetField();
1123+
await flushPromises();
1124+
1125+
expect(field.value.value).toBe('after change');
1126+
});
10621127
});

0 commit comments

Comments
 (0)