TanStack / form

🤖 Powerful and type-safe form state management for the web. TS/JS, React Form, Solid Form, Lit Form and Vue Form.

Home Page:https://tanstack.com/form

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Field Array Validation Not Refreshing Properly When Field is Removed

wscullen opened this issue · comments

Describe the bug

When multiple fields are added to a field array, and there is validation errors, if you update one of these fields to not have a validation error, and remove a field with a validation error (i - 1 to the good field), the removed field's validation error is applied to the field that does not have validation errors. It seems as though validation (or form state) is not properly re-evaluated and updated when a field is removed from a field array. Due to this bug, a call to form.validateAllFields("change") was attempted as a work around, but this results in the following error:

@tanstack_react-form.js?v=4b8d5915:1011 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'errorMap')
    at @tanstack_react-form…?v=4b8d5915:1011:25
    at functionalUpdate (@tanstack_react-form…s?v=4b8d5915:303:42)
    at @tanstack_react-form…s?v=4b8d5915:753:22
    at Store.setState (@tanstack_react-form…?v=4b8d5915:274:118)
    at FormApi.setFieldMeta (@tanstack_react-form…s?v=4b8d5915:748:18)
    at FieldApi.setMeta (@tanstack_react-form…s?v=4b8d5915:986:43)
    at @tanstack_react-form…?v=4b8d5915:1008:18
    at Store.batch (@tanstack_react-form.js?v=4b8d5915:292:7)
    at FieldApi.validateSync (@tanstack_react-form…s?v=4b8d5915:995:23)
    at FieldApi.validate (@tanstack_react-form…?v=4b8d5915:1106:35)
blitz.810981ba.js:352 

To view this error in the linked example project, uncomment out the indicated line 63 in the Form component.

Your minimal, reproducible example

https://stackblitz.com/edit/vitejs-vite-81fflp?file=src%2Fcomponents%2FForm.tsx

Steps to reproduce

  1. Add three people fields to the field array
  2. Click Submit to trigger validation
  3. Change the 3rd person's name to a valid value (any string), the validation error for that field will go away
  4. Remove the 2nd person from the field array by clicking the X

Result is the 2nd person (which was the 3rd person) now has the validation error showing of the previously deleted 2nd person.

To see the error, call form.validateAllFields("change") immediately after removing the field from the field array.

Expected behavior

I expect to see all validation for the 2nd person (previously the 3rd person) to continue to not have any errors, instead I'm seeing the previous validation error for the original 2nd person (which was removed).

When trying to work around the issue by manually revalidating all fields with form.validateAllFields("change") after the field is removed, errors are thrown (see above). This error can be avoided if the form.validateAllFields("change") call is placed in a setTimeout.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

macOS 12.7.2
chrome Version 122.0.6261.129 (Official Build) (arm64)

TanStack Form adapter

react-form

TanStack Form version

v0.16.0

TypeScript version

5.2.2

Additional context

No response

commented

Looks like we have a bug here, I'll check it out later this week! ☺️

commented

@crutchcorn You worked a lot on array fields, so I'll summon you to ask for help! 😆

If you check the video recording below, there are subfields in form.fieldMeta:

  • "people[0].name"
  • "people[1].name"

When we delete "people[0].name", the values in form.values are updated properly, but the meta data in form.fieldMeta do not, because "people[0].name" stays the same (instead of getting the value of "people[1].name"), and "people[1].name" simply gets deleted.

Kapture.2024-03-24.at.22.07.36.mp4

I could dig deeper, but I thought maybe you could give me some pointers here since you've worked with array fields recently. ☺️

@fulopkovacs do you think this is in part due to this? #662

commented

@fulopkovacs do you think this is in part due to this? #662

They might be related, but I tested the PR of the supposed fix for #662 (#700), and it seems like it does not solve the issue.

I'll look into it! (Thanks to #656, I'm much more comfortable with working on validation-related issues 🤣 )

commented

Ok, I found the bug and made a fix locally, I will try to clean it up and commit it this week.

The main source of the problem is that the array field is not re-validated after one of its subfields gets removed. But, here are some interesting things that I found when I was investigating the issue:

  • calling validate() on the array field itself did not re-validate the subfields (not sure if it's by accident or design), so I tried using validateAllFields() to quickly get the job done
  • validateAllFields() didn't work, because the fieldInfo property of FormApi still contained data related to the deleted field, and validateAllFields() relies on it to get the fields that should be validated
  • another fun fact: since the removeValue() method of FieldApi doesn't have an opts arg ({touch: boolean}), it can't pass it to this.form.removeFieldValue, which prevents the array field's meta data from being updated (it should happen here, it's fixed in #701 )

The fix I have locally deletes the data related to the last subfield from this.fieldInfo in removeFieldValue() before calling validateAllFields. This way we don't have errors and everything gets updated properly.