jaredpalmer / formik

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

FieldArray `errors` property splits string into an array #3352

Open eanyanwu opened 2 years ago

eanyanwu commented 2 years ago

Bug report

Current Behavior

Performing the following actions "mangles" the errors.<field> property:

By "mangle" i mean that the value of the error changes from "At least 2" to ["A"," ","l","e","a","s","t"," ","2"] (See reproduction)

Expected behavior

The value of the error should remain a string.

Reproducible example

https://codesandbox.io/s/strange-northcutt-4mol1

It's essentially the "FieldSet" example + yup validation + validateOnBlur/validateOnChange set to false

Suggested solution(s)

🤷🏽‍♂️ I unfortunately don't have the time to try to dig into why this is happening.

Additional context

This seems to have come up in previous issues (e.g. #2993 and #3178 ) I'm opening this because the previous one didn't seem to have a working repro.

Your environment

Software Version(s)
Formik 2.2.9
React 16.4.0
TypeScript N/A
Browser Firefox and Chrome
npm/Yarn ??? It's on codesandbox
Operating System macOS
sergei-maertens commented 9 months ago

Running into this as well at the moment, and the clue is in Formik's own documentation: https://formik.org/docs/api/fieldarray#fieldarray-validation-gotchas

The documentation describes the inside-out behaviour of Yup (but this problem is bigger than Yup alone) and is tied to the validation errors object having (or being recommended to have) the same structure as the values, so either:

The documentation (rightfully) warns for runtime checking the type of the error to prevent crashes, but this same type check is not performed in the array helpers implementation, causing the string mangling to happen:

  1. The remove (but other helpers likely also suffer from this) helper calls updateArrayField, to ensure that values, touched and errors are all updated
  2. copyArrayLike does not consider that the "array" could also be a string. Here the validation error gets turned into an array of charachters.
  3. In our case, the splice call actually causes our validation error to magically get characters removed, depending on the index of the item.

Likely the "container" function itself should already take this potential string type into account: https://github.com/jaredpalmer/formik/blob/0f960aaeeb0bdbef8312b5107cd3374884a0e62b/packages/formik/src/FieldArray.tsx#L194 as there it knows that it's dealing with errors and a string could be present. Doing this for the values and/or touched fields doesn't make sense.