jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.99k stars 2.79k forks source link

`yupToFormErrors` swallows some errors (specifically, errors on an array when the array contains objects with errors) #3841

Open anied opened 1 year ago

anied commented 1 year ago

Bug report

Current Behavior

When one has a Yup schema in which an array has its own validations as well as validations on the objects that it contains, the yupToFormErrors function in Formik overwrites the errors for the array itself with the errors on the contents of the array in the returned errors object.

Here is an example schema:

const schema = object({
  employees: array()
    .of(
      object({
        name: string().required('name is required'),
        isManager: boolean(),
      })
    )
    .test(
      'hasEmployees',
      'enter at least one employee',
      (value) => (value?.length ?? 0) > 0
    )
    .test('hasManager', 'at least one employee must be a manager', (value) =>
      value.some((employee) => employee.isManager)
    ),
});

In this case, were this to validate the value:

{
  employees: [
    { name: 'Joey', isManager: false },
    { name: '', isManager: false },
  ],
}

Yup would output that there is a validation error on the second employee (missing the name property) as well as the entire array (doesn't have a manager) but the resulting resolved Formik errors only show:

{
  employees: [
    undefined,
    { name: 'name is required' },
  ],
}

Expected behavior

I would expect there to be some means of represent both sets of errors.

Reproducible example

https://codesandbox.io/s/formik-bug-swallows-some-errors-forked-3t2hsn

Suggested solution(s)

Arrays are objects in JS, so in theory we could give it some properties itself, but that's probably an antipattern. We could break out a separate property for the array itself in the errors object, maybe { _employees: "at least one employee must be a manager" }. Or we could provide an option to <Formik/> (and the other forms) to provide the errors as a flat list, instead of an object? There might be a better solution I'm just not thinking of.

Additional context

None.

Your environment

Software Version(s)
Formik 2.2.6
React 17.0.2
TypeScript n/a
Browser Chrome Version 114.0.5735.133 (Official Build) (arm64)
npm/Yarn npm 9.5.0
Operating System MacOS Ventura 13.4 (22F66)