Skip to content

fix: restore useField meta object reactivity sync (#5021)#5135

Open
logaretm wants to merge 1 commit intomainfrom
fix/5021-usefield-meta-sync
Open

fix: restore useField meta object reactivity sync (#5021)#5135
logaretm wants to merge 1 commit intomainfrom
fix/5021-usefield-meta-sync

Conversation

@logaretm
Copy link
Copy Markdown
Owner

@logaretm logaretm commented Mar 4, 2026

Summary

Fixes #5021. Since v4.12.0, calling useField with the same field path in multiple components (e.g. parent and child) within the same form context created 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 PR restores the v4.11.8 behavior:

  • createPathState: Returns the existing PathState for 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 operations
  • removePathState: Decrements fieldsCount for all shared fields and only removes the PathState when the count reaches zero
  • useField unmount: Fixes matchesId check to handle array IDs for non-multiple shared fields, and only unsets path values when it is the last field or a radio/checkbox group

Test plan

  • Added regression test: 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
  • All existing tests pass (356 passed, 3 skipped; 3 pre-existing infrastructure failures unrelated to this change)
  • Radio button unmount tests still pass
  • Field array insert/remove tests still pass
  • Existing meta sync tests (valid flag, dirty flag, reset) still pass

🤖 Generated with Claude Code

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>
Copilot AI review requested due to automatic review settings March 4, 2026 06:38
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 4, 2026

🦋 Changeset detected

Latest 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

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 4, 2026

Deploy Preview for vee-validate-v5 ready!

Name Link
🔨 Latest commit 7918fe8
🔍 Latest deploy log https://app.netlify.com/projects/vee-validate-v5/deploys/69a7d364a4a1c9000849cc57
😎 Deploy Preview https://deploy-preview-5135--vee-validate-v5.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 4, 2026

Deploy Preview for vee-validate-docs canceled.

Name Link
🔨 Latest commit 7918fe8
🔍 Latest deploy log https://app.netlify.com/projects/vee-validate-docs/deploys/69a7d36461df2d0008df8e33

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 4, 2026

👷 Deploy Preview for vee-validate-docs processing.

Name Link
🔨 Latest commit 7918fe8
🔍 Latest deploy log https://app.netlify.com/projects/vee-validate-docs/deploys/69a7d36461df2d0008df8e33

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 fieldsCount for all field types and only remove a PathState once the count reaches zero.
  • Add/adjust regression tests to verify shared meta behavior and updated PathState.id representation.

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.id is mutated (spliced) before calling form.removePathState(path, id). Since removePathState locates the PathState by checking whether id is still present in state.id, removing it early can make removePathState fail to find the state, leaving fieldsCount un-decremented and preventing proper cleanup/removal when the last checkbox unmounts. Consider letting removePathState own the id removal (remove the splice here), or call removePathState before mutating pathState.id / adjust removePathState lookup so it can still find the state after local id mutation.
      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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking Change in useField Behavior After v4.11.8 - meta object no longer syncs

2 participants