Formik: FormArrays validation with Yup problem with ErrorMessage

Created on 9 Dec 2018  路  8Comments  路  Source: formium/formik

馃悰 Bug report

Current Behavior

When validating an array with Yup, should be able to display errors in one ErrorMessage component for the array errors and with one ErrorMessage for each field of the array.
When using Yup, I have an unexpected behavior:

  • if the internal requirements of the array are met, the ErrorMessage of the array displays the right message.
  • however, each ErrorMessage component of each array field displays the first, then the second and so on letter of the general ErrorMessage. The ErrorMessage of the array is displaying the right error message.

Expected behavior

When internal requirements are met, only the "general" ErrorMessage-meaning the error component for the Array taken globally- should be displayed.

Reproducible example [MAJ with @barrett-vegas-com input]

https://codesandbox.io/s/35yz2my6q

Suggested solution(s)

No suggested solution

Your environment

Linux

| Software | Version(s) |
| ---------------- | ---------- |
| Formik | 1.4.0
| React | 16.6.3

stale

All 8 comments

@dymafr I thought I had the same issue as you, but after correcting some errors in your codesandbox example I don't see the issues you describe, nor the issue I thought I was having. Here is the corrected example: https://codesandbox.io/s/740xm1jq10

@barrett-vegas-com
Thank you very much for your time and input!
However, if you remove:
props.children.length > 1

It will have the bug as described. I updated the question with your sandbox and just removed this code.
You can still see the "V" and "o".

I think this is an incorrect behavior

Ah, then that is the same issue I'm having ;) Thanks!

The issue seems to stem from using something like getIn(errors, 'myArray[0]') when the errors could look like:

{
  errors: {
    myArray: 'The top level array has an issue'
  }
}

or

{
  errors: {
    myArray: ['The first element has an issue']
  }
}

In the first case getIn will return the first letter T of the String, while in the second case it'll return the full error message for the field.

@jaredpalmer Do you need some more input on this issue? Thanks a lot

I just ran into this too. It looks like this block is why this is happening:

https://github.com/jaredpalmer/formik/blob/master/src/Formik.tsx#L685-L688

When using a yup.array() schema, and multiple items in the array are invalid, the ValidationError object will show separate errors for each item. Looking something like:

ValidationError { 
  inner: [
    { path: someField[0], message: 'Invalid Field', ... },
    { path: someField[3], message: 'Invalid Field', ... }
  ],
  ...
}

then yupToFormErrors recreates that structure using setIn so the yup errors object will have an array of error messages for someField. Like,

FormikBag.errors {
  someField: ['Invalid Field', undefined, undefined, 'Invalid Field']
}

then ErrorMessage is probably just rendering the array with React, which is why it looks like

Invalid FieldInvalid Field

I'm not sure that this is bad behavior or not but I do think it breaks ErrorMessage's expectation that error messages are strings.

This still appears to be an issue.

image

Anyone who see's this thread, the workaround I used was:

.test({
        name: "minDefined",
        message: "You must specify at least one publication. You can always change this later!",
        test: function(value) {
          return !(this.path === "websites[0]" && this.parent.filter(val => val !== "").length === 0);
        }
      })

Essentially it runs the test that should be on the outside of the array on the inside and ensures it only runs for the first index.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PeerHartmann picture PeerHartmann  路  3Comments

dearcodes picture dearcodes  路  3Comments

outaTiME picture outaTiME  路  3Comments

jaredpalmer picture jaredpalmer  路  3Comments

najisawas picture najisawas  路  3Comments