-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix: clean up validation state when fields are unmounted #5134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "vee-validate": patch | ||
| --- | ||
|
|
||
| Fix validation results persisting for fields that are no longer rendered (#4982) |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -129,6 +129,10 @@ export function useForm< | |||||||
|
|
||||||||
| const extraErrorsBag: Ref<FormErrorBag<TValues>> = ref({}); | ||||||||
|
|
||||||||
| // Tracks paths that are being removed due to field unmount, to prevent | ||||||||
| // re-validation from adding errors back for fields that are no longer rendered (#4982) | ||||||||
| const REMOVED_PATHS = new Set<string>(); | ||||||||
|
|
||||||||
| const pathStateLookup = ref<Record<string, PathState>>({}); | ||||||||
|
|
||||||||
| const rebuildPathLookup = debounceNextTick(() => { | ||||||||
|
|
@@ -287,6 +291,9 @@ export function useForm< | |||||||
| UNSET_BATCH.splice(unsetBatchIndex, 1); | ||||||||
| } | ||||||||
|
|
||||||||
| // Clear removed path tracking when a field is re-mounted (#4982) | ||||||||
| REMOVED_PATHS.delete(pathValue); | ||||||||
|
|
||||||||
| const id = FIELD_ID_COUNTER++; | ||||||||
| const state = reactive({ | ||||||||
| id, | ||||||||
|
|
@@ -388,7 +395,10 @@ export function useForm< | |||||||
|
|
||||||||
| // field not rendered | ||||||||
| if (!pathState) { | ||||||||
| setFieldError(path, messages); | ||||||||
| // Skip setting errors for paths that were explicitly removed due to field unmount (#4982) | ||||||||
| if (!REMOVED_PATHS.has(path)) { | ||||||||
| setFieldError(path, messages); | ||||||||
| } | ||||||||
|
|
||||||||
| return validation; | ||||||||
| } | ||||||||
|
|
@@ -437,6 +447,14 @@ export function useForm< | |||||||
| setFieldError(pathState, results.results[path]?.errors); | ||||||||
| }); | ||||||||
|
|
||||||||
| // Clean up errors and tracking for paths that were removed due to field unmount (#4982) | ||||||||
| if (REMOVED_PATHS.size) { | ||||||||
| REMOVED_PATHS.forEach(path => { | ||||||||
| delete extraErrorsBag.value[path as Path<TValues>]; | ||||||||
|
||||||||
| delete extraErrorsBag.value[path as Path<TValues>]; | |
| const normalizedPath = normalizeFormPath(path as string) as Path<TValues>; | |
| delete extraErrorsBag.value[normalizedPath]; |
Copilot
AI
Mar 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
REMOVED_PATHS stores the raw path string, but schema validation (notably standard-schema adapters) can produce dot-indexed paths like users.0.name, while setFieldError/extraErrorsBag normalize to bracket syntax (users[0].name). This mismatch means removed array/nested paths may not be recognized as removed and can have errors re-added. Normalize the path consistently (e.g., store and delete normalizeFormPath(path) in REMOVED_PATHS).
| REMOVED_PATHS.add(path); | |
| const normalizedPath = normalizeFormPath(path); | |
| REMOVED_PATHS.add(normalizedPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the “field not rendered” branch, the
REMOVED_PATHS.has(path)check uses the unnormalizedpathvalue. For standard-schema results,pathmay be dot-indexed (e.g.arr.0.foo) while removed paths are typically tracked as bracket paths (e.g.arr[0].foo), so this check can fail and errors get re-added. Consider normalizing thepathbefore checking/setting errors so removed paths are reliably skipped.