Skip to content

Commit 74af33e

Browse files
kusiewiczLeCarbonatorautofix-ci[bot]
authored
fix(form-core): prevent runtime errors when using deleteField (#1706)
* fix(core): fix deleteField method * Create healthy-forks-live.md * ci: apply automated fixes and generate docs * Update healthy-forks-live.md * chore: add tests * ci: apply automated fixes and generate docs --------- Co-authored-by: LeCarbonator <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent efa5dd7 commit 74af33e

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

.changeset/healthy-forks-live.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/form-core': patch
3+
---
4+
5+
fix(form-core): prevent runtime errors when using `deleteField`

packages/form-core/src/FormApi.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,11 @@ export class FormApi<
16421642
for (const field of Object.keys(
16431643
this.state.fieldMeta,
16441644
) as DeepKeys<TFormData>[]) {
1645+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1646+
if (this.baseStore.state.fieldMetaBase[field] === undefined) {
1647+
continue
1648+
}
1649+
16451650
const fieldMeta = this.getFieldMeta(field)
16461651
if (!fieldMeta) continue
16471652

@@ -1845,6 +1850,11 @@ export class FormApi<
18451850
for (const field of Object.keys(
18461851
this.state.fieldMeta,
18471852
) as DeepKeys<TFormData>[]) {
1853+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1854+
if (this.baseStore.state.fieldMetaBase[field] === undefined) {
1855+
continue
1856+
}
1857+
18481858
const fieldMeta = this.getFieldMeta(field)
18491859
if (!fieldMeta) continue
18501860

packages/react-form/tests/useForm.test.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,4 +892,70 @@ describe('useForm', () => {
892892
await user.click(target)
893893
expect(result).toHaveTextContent('1')
894894
})
895+
896+
it('should not error when using deleteField in edge cases', async () => {
897+
function Comp() {
898+
const form = useForm({
899+
defaultValues: {
900+
firstName: '',
901+
lastName: '',
902+
},
903+
validators: {
904+
onChange: ({ value }) => {
905+
const fields: Record<string, string> = {}
906+
907+
if (value.firstName.length === 0) {
908+
fields.firstName = 'Last Name is required'
909+
}
910+
911+
return { fields }
912+
},
913+
},
914+
})
915+
916+
return (
917+
<form
918+
onSubmit={(e) => {
919+
e.preventDefault()
920+
form.handleSubmit()
921+
}}
922+
>
923+
<h1>Personal Information</h1>
924+
<form.Field
925+
name="firstName"
926+
children={(field) => (
927+
<input
928+
data-testid="input"
929+
value={field.state.value}
930+
onChange={(e) => field.handleChange(e.target.value)}
931+
/>
932+
)}
933+
/>
934+
<form.Field
935+
name="lastName"
936+
children={(field) => (
937+
<input
938+
value={field.state.value}
939+
onChange={(e) => field.handleChange(e.target.value)}
940+
/>
941+
)}
942+
/>
943+
<button
944+
type="button"
945+
data-testid="remove"
946+
onClick={() => form.deleteField('firstName')}
947+
>
948+
remove first name
949+
</button>
950+
</form>
951+
)
952+
}
953+
954+
const { getByTestId } = render(<Comp />)
955+
const removeButton = getByTestId('remove')
956+
const input = getByTestId('input')
957+
958+
await user.type(input, 'a')
959+
await user.click(removeButton)
960+
})
895961
})

0 commit comments

Comments
 (0)