fix: initial meta.valid is false with schema (#4855)#5127
fix: initial meta.valid is false with schema (#4855)#5127
Conversation
Previously meta.valid started as true due to vacuous truth from [].every(). Now correctly returns false when a schema exists but fields haven't been validated yet, and new PathState entries start with valid: false when a schema is present. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 469669a 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. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
✅ Deploy Preview for vee-validate-docs canceled.
|
There was a problem hiding this comment.
Pull request overview
Fixes meta.valid reporting true initially when a validation schema is present but no fields/path states have been validated/registered yet (issue #4855), avoiding the [].every(...) === true vacuous-truth edge case.
Changes:
- Passes schema presence into
useFormMetaand forcesvalid=falsewhen a schema exists and there are no path states. - Initializes new
PathState.validtofalsewhen a schema is present. - Adds/updates tests around initial
meta.validbehavior with/without schemas.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/vee-validate/src/useForm.ts | Adjusts initial valid defaults and form meta aggregation to account for schema + empty path state scenarios. |
| packages/vee-validate/tests/useForm.spec.ts | Adds new tests for initial meta.valid with and without a schema. |
| packages/vee-validate/tests/useFieldArray.spec.ts | Updates existing field array tests to align with the new initial meta.valid semantics. |
Comments suppressed due to low confidence (7)
packages/vee-validate/src/useForm.ts:248
useFormMetais passed!!opts?.validationSchema, butvalidationSchemasupports refs/computed (seeisRef(schema)watcher).!!opts.validationSchemawill betruefor a ref even whenunref(schema)is currentlynull/undefined, and it won’t update if the schema ref toggles. Consider passing a reactive boolean derived fromunref(schema)(or passingschemaintouseFormMetaand unref’ing inside) someta.validreflects whether a schema is actually active.
// form meta aggregations
const meta = useFormMeta(pathStates, formValues, originalInitialValues, errors, !!opts?.validationSchema);
packages/vee-validate/src/useForm.ts:1131
- The vacuous-truth override (
flag === 'valid' && hasSchema && !states.length) depends onhasSchema, butvalidationSchemasupports refs/computed. If the schema ref toggles while there are no path states, a non-reactive boolean can makemeta.validincorrect. Consider makinghasSchemareactive (derived fromunref(schema)each time) so this stays in sync.
if (flag === 'valid' && hasSchema && !states.length) {
acc[flag] = false;
} else {
acc[flag] = states[mergeMethod](s => s[flag]);
packages/vee-validate/tests/useFieldArray.spec.ts:192
- This test no longer asserts the initial
form.meta.value.validstate; it was replaced by a comment. Since the behavior change in #4855 is specifically about the initialmeta.validvalue when a schema exists and no path states are registered, add an explicit expectation here (beforearr.push) so the regression is actually covered by the test.
await flushPromises();
// With a schema and no registered field path states, meta.valid is false (#4855)
arr.push('');
await flushPromises();
packages/vee-validate/tests/useFieldArray.spec.ts:248
- This test removed the assertion of the initial
form.meta.value.validvalue and left only a comment. Add an explicitexpect(form.meta.value.valid).toBe(false)(beforearr.prepend) to ensure the updated #4855 behavior is actually exercised.
await flushPromises();
// With a schema and no registered field path states, meta.valid is false (#4855)
arr.prepend('');
await flushPromises();
packages/vee-validate/tests/useFieldArray.spec.ts:304
- This test similarly replaced the initial
meta.validassertion with a comment. Add an explicit expectation beforearr.insertso the initial invalid state with a schema and no registered path states is verified (not just implied).
await flushPromises();
// With a schema and no registered field path states, meta.valid is false (#4855)
arr.insert(1, '');
await flushPromises();
packages/vee-validate/tests/useForm.spec.ts:1502
- This test registers a field (
useField('name')), so it doesn’t exercise theuseFormMetavacuous-truth fix (schema present +pathStatesstill empty). Add a test that providesvalidationSchemabut registers no fields, and assertform.meta.value.validisfalseinitially.
form = useForm({
initialValues: { name: '' },
validationSchema: {
name(value: string) {
return value ? true : 'Name is required';
packages/vee-validate/tests/useForm.spec.ts:1499
- These new tests type
formasRecord<string, any>, while the rest of this file commonly usesFormContext<...>foruseForm()results. UsingFormContexthere would keep the test typings consistent and provide better compile-time checking of the API surface.
let form!: Record<string, any>;
mountWithHoc({
setup() {
form = useForm({
initialValues: { name: '' },
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| touched: false, | ||
| pending: false, | ||
| valid: true, | ||
| valid: !schema, |
There was a problem hiding this comment.
valid: !schema is incorrect when validationSchema is passed as a Ref/computed (supported elsewhere in this file): the ref object is always truthy, so new path states start invalid even if unref(schema) is currently falsy. Initialize this flag from the schema value (e.g. !unref(schema)) to stay consistent with how formCtx.validateSchema is enabled.
| valid: !schema, | |
| valid: !unref(schema), |
Summary
meta.validincorrectly started astrueeven when a validation schema was provided and fields hadn't been validated yet[].every(() => ...)returnstrue(vacuous truth). When no path states existed yet,useFormMetacomputedvalidastruevalid: falsewhen a schema is present, anduseFormMetareturnsfalsefor thevalidflag when there are no path states but a schema existsTest plan
meta.validshould befalseinitially when a validation schema is providedmeta.validshould betrueinitially when no validation schema is provideduseFieldArraytests that incorrectly assumedvalid: truewith a schema and no registered field path states🤖 Generated with Claude Code