fix: restore useField meta object reactivity sync (#5021)#5135
fix: restore useField meta object reactivity sync (#5021)#5135
Conversation
Since v4.12.0, calling useField with the same path in multiple components (e.g. parent and child) within the same form would create separate PathState objects instead of sharing one. This broke meta object synchronization — touching a field in the child would not update the parent's meta. The regression was introduced when createPathState was changed to only reuse existing path states for checkbox/radio fields. This restores the v4.11.8 behavior where all field types sharing a path reuse the same PathState, while also: - Adding a path identity check to avoid reusing stale path states in field array scenarios where paths shift (e.g. after insert) - Updating removePathState to properly decrement fieldsCount for all shared fields (not just checkbox/radio) - Fixing the unmount logic to handle array IDs for non-multiple shared fields - Only unsetting path values on unmount when it is the last field or a radio/checkbox group Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 7918fe8 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for vee-validate-v5 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for vee-validate-docs canceled.
|
👷 Deploy Preview for vee-validate-docs processing.
|
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression introduced in v4.12.0 where multiple useField() calls for the same path within the same form context no longer shared a single PathState, breaking meta synchronization between components (issue #5021).
Changes:
- Restore
createPathState()reuse for all field types sharing the same path (with a normalized-path identity check to avoid reusing stale states in field array scenarios). - Track shared registrations via
fieldsCountfor all field types and only remove aPathStateonce the count reaches zero. - Add/adjust regression tests to verify shared
metabehavior and updatedPathState.idrepresentation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/vee-validate/src/useForm.ts | Reuse PathState for same-path fields and manage shared lifecycle via fieldsCount. |
| packages/vee-validate/src/useField.ts | Adjust unmount behavior to work with shared PathState.id arrays and avoid unsetting shared values prematurely. |
| packages/vee-validate/tests/useField.spec.ts | Add regression test validating meta sync across multiple useField() calls for the same path. |
| packages/vee-validate/tests/Form.spec.ts | Update expectations to reflect shared PathState (single state with id: number[]). |
| .changeset/fix-5021-usefield-meta-sync.md | Add patch changeset entry for the regression fix. |
Comments suppressed due to low confidence (1)
packages/vee-validate/src/useField.ts:409
- In the checkbox-group unmount branch,
pathState.idis mutated (spliced) before callingform.removePathState(path, id). SinceremovePathStatelocates thePathStateby checking whetheridis still present instate.id, removing it early can makeremovePathStatefail to find the state, leavingfieldsCountun-decremented and preventing proper cleanup/removal when the last checkbox unmounts. Consider lettingremovePathStateown theidremoval (remove the splice here), or callremovePathStatebefore mutatingpathState.id/ adjustremovePathStatelookup so it can still find the state after localidmutation.
if (Array.isArray(pathState.id)) {
pathState.id.splice(pathState.id.indexOf(field.id), 1);
}
} else if (pathState?.multiple || pathState?.fieldsCount <= 1) {
form.unsetPathValue(toValue(name));
}
form.removePathState(path, id);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Fixes #5021. Since v4.12.0, calling
useFieldwith the same field path in multiple components (e.g. parent and child) within the same form context created separatePathStateobjects instead of sharing one. This brokemetaobject synchronization — touching a field in the child would not update the parent'smeta.The regression was introduced when
createPathStatewas changed to only reuse existing path states for checkbox/radio fields. This PR restores the v4.11.8 behavior:createPathState: Returns the existingPathStatefor all field types sharing a path (not just checkbox/radio), with a path identity check to avoid reusing stale path states in field array scenarios where paths shift after insert/remove operationsremovePathState: DecrementsfieldsCountfor all shared fields and only removes thePathStatewhen the count reaches zerouseFieldunmount: FixesmatchesIdcheck to handle array IDs for non-multiple shared fields, and only unsets path values when it is the last field or a radio/checkbox groupTest plan
meta object syncs between multiple useField calls for the same path within a form— verifies that touching a field in a child component updates the parent's meta🤖 Generated with Claude Code