Skip to content

Deleting field keeps data from subfields #1178

@LeCarbonator

Description

@LeCarbonator

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

  1. Enter stackblitz
  2. Touch Robert's text input => canSubmit should now be false
  3. Delete Robert by calling deleteField('people.Robert')
  4. canSubmit = false, no matter if Martha's input is correct.
  5. 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>);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions