- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 536
Description
Describe the bug
When calling <ReactExtendedFormApi>#deleteField(), subfields persist even after the parent field is deleted.
If subfields were invalid at point of deletion, the form is stuck in an invalid state and can no longer be submitted.
Your minimal, reproducible example
https://stackblitz.com/edit/bolt-vite-react-8afzqlnr?file=src%2FApp.tsx
Steps to reproduce
- Enter stackblitz
- Touch Robert's text input => canSubmitshould now befalse
- Delete Robert by calling deleteField('people.Robert')
- canSubmit = false, no matter if Martha's input is correct.
- The form is stuck in an invalid state
Expected behavior
I expected subfields to also be deleted when deleting the parent field, but instead got stuck in a locked state.
Example use case: useForm for labeled columns, with options to add or remove columns. I experienced the invalid state when adding an empty column (which is invalid), then deleting it again.
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
- Windows 11
- Firefox v135.0.1
TanStack Form adapter
None
TanStack Form version
v0.44.0
TypeScript version
v5.5.3
Additional context
For users experiencing the same issue, here's a hacky solution to get by until this is fixed:
Note that this solution was specifically made for ^0.42.0, as that is the version our repository uses.
The stackblitz is on v0.44.0, so this issue is not yet resolved on the latest version at this issue's creation.
/**
 * Deletes a tanstack form field and all subfields belonging to that field.
 * Note that this is an external function, and should not be used over internal ones.
 * - For leaf fields, use `form.deleteField()` instead.
 * - For arrays, use `form.removeFieldValue()` instead.
 * @param form The form instance to remove values from.
 * @param key The key to remove. Removes all subfields as well.
 * @example `editors.${key}` // also matches `editors.${key}.visibility`
 */
export function deleteFormFieldAndChildren<TParentData>(form: ReactFormExtendedApi<TParentData, any>, key: string) {
  const deleteKeys = Object.keys(form.fieldInfo).filter(s => s.startsWith(key));
  for (const k of deleteKeys) {
    form.deleteField(k as DeepKeys<TParentData>);
  }
  // there's some shenanigangs behind the scenes affecting `form.state.values`. Delete the main key again
  // to ensure there's no explicitly set undefined keys.
  form.deleteField(key as DeepKeys<TParentData>);
}