Skip to content

Commit

Permalink
fix: meta should not regenerate every render (#1114)
Browse files Browse the repository at this point in the history
* fix: meta should not regenerate every render

* ci: apply automated fixes and generate docs

* chore: tests now pass

* ci: apply automated fixes and generate docs

* chore: add test to validate patch

* chore: fix linter

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
crutchcorn and autofix-ci[bot] authored Jan 15, 2025
1 parent b60264c commit 08d610f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 23 deletions.
42 changes: 21 additions & 21 deletions docs/reference/classes/formapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Defined in: [packages/form-core/src/FormApi.ts:377](https://github.com/TanStack/
deleteField<TField>(field): void
```
Defined in: [packages/form-core/src/FormApi.ts:1182](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1182)
Defined in: [packages/form-core/src/FormApi.ts:1194](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1194)
#### Type Parameters
Expand All @@ -143,7 +143,7 @@ Defined in: [packages/form-core/src/FormApi.ts:1182](https://github.com/TanStack
getFieldInfo<TField>(field): FieldInfo<TFormData, TFormValidator>
```
Defined in: [packages/form-core/src/FormApi.ts:1091](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1091)
Defined in: [packages/form-core/src/FormApi.ts:1103](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1103)
Gets the field info of the specified field.
Expand All @@ -169,7 +169,7 @@ Gets the field info of the specified field.
getFieldMeta<TField>(field): undefined | FieldMeta
```
Defined in: [packages/form-core/src/FormApi.ts:1082](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1082)
Defined in: [packages/form-core/src/FormApi.ts:1094](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1094)
Gets the metadata of the specified field.
Expand All @@ -195,7 +195,7 @@ Gets the metadata of the specified field.
getFieldValue<TField>(field): DeepValue<TFormData, TField, IsNullable<TFormData>>
```
Defined in: [packages/form-core/src/FormApi.ts:1075](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1075)
Defined in: [packages/form-core/src/FormApi.ts:1087](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1087)
Gets the value of the specified field.
Expand All @@ -221,7 +221,7 @@ Gets the value of the specified field.
handleSubmit(): Promise<void>
```
Defined in: [packages/form-core/src/FormApi.ts:1016](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1016)
Defined in: [packages/form-core/src/FormApi.ts:1028](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1028)
Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.
Expand All @@ -241,7 +241,7 @@ insertFieldValue<TField>(
opts?): Promise<void>
```
Defined in: [packages/form-core/src/FormApi.ts:1214](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1214)
Defined in: [packages/form-core/src/FormApi.ts:1226](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1226)
Inserts a value into an array field at the specified index, shifting the subsequent values to the right.
Expand Down Expand Up @@ -279,7 +279,7 @@ Inserts a value into an array field at the specified index, shifting the subsequ
mount(): () => void
```
Defined in: [packages/form-core/src/FormApi.ts:595](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L595)
Defined in: [packages/form-core/src/FormApi.ts:607](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L607)
#### Returns
Expand All @@ -301,7 +301,7 @@ moveFieldValues<TField>(
opts?): void
```
Defined in: [packages/form-core/src/FormApi.ts:1332](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1332)
Defined in: [packages/form-core/src/FormApi.ts:1344](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1344)
Moves the value at the first specified index to the second specified index within an array field.
Expand Down Expand Up @@ -342,7 +342,7 @@ pushFieldValue<TField>(
opts?): void
```
Defined in: [packages/form-core/src/FormApi.ts:1196](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1196)
Defined in: [packages/form-core/src/FormApi.ts:1208](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1208)
Pushes a value into an array field.
Expand Down Expand Up @@ -379,7 +379,7 @@ removeFieldValue<TField>(
opts?): Promise<void>
```
Defined in: [packages/form-core/src/FormApi.ts:1267](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1267)
Defined in: [packages/form-core/src/FormApi.ts:1279](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1279)
Removes a value from an array field at the specified index.
Expand Down Expand Up @@ -417,7 +417,7 @@ replaceFieldValue<TField>(
opts?): Promise<void>
```
Defined in: [packages/form-core/src/FormApi.ts:1241](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1241)
Defined in: [packages/form-core/src/FormApi.ts:1253](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1253)
Replaces a value into an array field at the specified index.
Expand Down Expand Up @@ -455,7 +455,7 @@ Replaces a value into an array field at the specified index.
reset(values?, opts?): void
```
Defined in: [packages/form-core/src/FormApi.ts:656](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L656)
Defined in: [packages/form-core/src/FormApi.ts:668](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L668)
Resets the form state to the default values.
If values are provided, the form will be reset to those values instead and the default values will be updated.
Expand Down Expand Up @@ -488,7 +488,7 @@ Optional options to control the reset behavior.
resetFieldMeta<TField>(fieldMeta): Record<TField, FieldMeta>
```
Defined in: [packages/form-core/src/FormApi.ts:1128](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1128)
Defined in: [packages/form-core/src/FormApi.ts:1140](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1140)
#### Type Parameters
Expand All @@ -512,7 +512,7 @@ Defined in: [packages/form-core/src/FormApi.ts:1128](https://github.com/TanStack
setErrorMap(errorMap): void
```
Defined in: [packages/form-core/src/FormApi.ts:1356](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1356)
Defined in: [packages/form-core/src/FormApi.ts:1368](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1368)
Updates the form's errorMap
Expand All @@ -534,7 +534,7 @@ Updates the form's errorMap
setFieldMeta<TField>(field, updater): void
```
Defined in: [packages/form-core/src/FormApi.ts:1110](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1110)
Defined in: [packages/form-core/src/FormApi.ts:1122](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1122)
Updates the metadata of the specified field.
Expand Down Expand Up @@ -567,7 +567,7 @@ setFieldValue<TField>(
opts?): void
```
Defined in: [packages/form-core/src/FormApi.ts:1152](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1152)
Defined in: [packages/form-core/src/FormApi.ts:1164](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1164)
Sets the value of the specified field and optionally updates the touched state.
Expand Down Expand Up @@ -605,7 +605,7 @@ swapFieldValues<TField>(
opts?): void
```
Defined in: [packages/form-core/src/FormApi.ts:1306](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1306)
Defined in: [packages/form-core/src/FormApi.ts:1318](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1318)
Swaps the values at the specified indices within an array field.
Expand Down Expand Up @@ -643,7 +643,7 @@ Swaps the values at the specified indices within an array field.
update(options?): void
```
Defined in: [packages/form-core/src/FormApi.ts:612](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L612)
Defined in: [packages/form-core/src/FormApi.ts:624](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L624)
Updates the form options and form state.
Expand All @@ -665,7 +665,7 @@ Updates the form options and form state.
validateAllFields(cause): Promise<ValidationError[]>
```
Defined in: [packages/form-core/src/FormApi.ts:682](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L682)
Defined in: [packages/form-core/src/FormApi.ts:694](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L694)
Validates form and all fields in using the correct handlers for a given validation cause.
Expand All @@ -690,7 +690,7 @@ validateArrayFieldsStartingFrom<TField>(
cause): Promise<ValidationError[]>
```
Defined in: [packages/form-core/src/FormApi.ts:710](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L710)
Defined in: [packages/form-core/src/FormApi.ts:722](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L722)
Validates the children of a specified array in the form starting from a given index until the end using the correct handlers for a given validation type.
Expand Down Expand Up @@ -726,7 +726,7 @@ validateField<TField>(field, cause):
| Promise<ValidationError[]>
```
Defined in: [packages/form-core/src/FormApi.ts:749](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L749)
Defined in: [packages/form-core/src/FormApi.ts:761](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L761)
Validates a specified field in the form using the correct handlers for a given validation type.
Expand Down
16 changes: 14 additions & 2 deletions packages/form-core/src/FormApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,10 @@ export class FormApi<
fieldName as never
] as FieldMetaBase | undefined

let fieldErrors =
prevVal?.[fieldName as never as keyof typeof prevVal]?.errors
const prevFieldInfo =
prevVal?.[fieldName as never as keyof typeof prevVal]

let fieldErrors = prevFieldInfo?.errors
if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter(
Expand All @@ -428,6 +430,16 @@ export class FormApi<
// As a primitive, we don't need to aggressively persist the same referencial value for performance reasons
const isFieldPristine = !currBaseVal.isDirty

if (
prevFieldInfo &&
prevFieldInfo.isPristine === isFieldPristine &&
prevFieldInfo.errors === fieldErrors &&
currBaseVal === prevBaseVal
) {
fieldMeta[fieldName] = prevFieldInfo
continue
}

fieldMeta[fieldName] = {
...currBaseVal,
errors: fieldErrors,
Expand Down
62 changes: 62 additions & 0 deletions packages/react-form/tests/useField.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react-compiler/react-compiler */
import { describe, expect, it, vi } from 'vitest'
import { render, waitFor } from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
Expand Down Expand Up @@ -1068,4 +1069,65 @@ describe('useField', () => {
await user.click(getByText('Add person'))
expect(getByText(`["Test"]`)).toBeInTheDocument()
})

it('should not rerender unrelated fields', async () => {
const renderCount = {
field1: 0,
field2: 0,
}

function Comp() {
const form = useForm({
defaultValues: {
field1: '',
field2: '',
},
})

return (
<>
<form.Field name="field1">
{(field) => {
renderCount.field1++
return (
<input
data-testid="field1"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
)
}}
</form.Field>
<form.Field name="field2">
{(field) => {
renderCount.field2++
return (
<input
data-testid="field2"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
)
}}
</form.Field>
</>
)
}

const { getByTestId } = render(
<StrictMode>
<Comp />
</StrictMode>,
)

const field1InitialRender = renderCount.field1
const field2InitialRender = renderCount.field2

await user.type(getByTestId('field1'), 'test')

// field1 should have rerendered
expect(renderCount.field1).toBeGreaterThan(field1InitialRender)
// field2 should not have rerendered
expect(renderCount.field2).toBe(field2InitialRender)
})
})

0 comments on commit 08d610f

Please sign in to comment.