From 62a9bdd6354d0b5d47683edac6ba9c55a436cf49 Mon Sep 17 00:00:00 2001 From: Diogo Esteves Date: Sat, 24 Oct 2026 15:12:03 +0100 Subject: [PATCH 1/3] docs(react): document field state reactivity Explain that field state read inside `form.Field` and in field components using `useFieldContext` is kept up to date, note the array-mode exception, and show `useSelector(field.store, ...)`. Update the pre-bound `TextField` example to handle blur and show the field's errors. Closes #1207 --- docs/framework/react/guides/form-composition.md | 6 ++++++ docs/framework/react/guides/reactivity.md | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/docs/framework/react/guides/form-composition.md b/docs/framework/react/guides/form-composition.md index cf2db1cc19..c84e6a4307 100644 --- a/docs/framework/react/guides/form-composition.md +++ b/docs/framework/react/guides/form-composition.md @@ -66,12 +66,18 @@ export function TextField({ label }: { label: string }) { field.handleChange(e.target.value)} + onBlur={field.handleBlur} /> + {!field.state.meta.isValid && ( + {field.state.meta.errors.join(', ')} + )} ) } ``` +The component re-renders whenever the field's value or meta changes, so `field.state` is always up to date here. See [Reactivity](./reactivity.md#field-state) for details. + You're then able to register this component with your form hook. ```tsx diff --git a/docs/framework/react/guides/reactivity.md b/docs/framework/react/guides/reactivity.md index d85b6bdbec..5a0f638e3c 100644 --- a/docs/framework/react/guides/reactivity.md +++ b/docs/framework/react/guides/reactivity.md @@ -54,3 +54,19 @@ The `form.Subscribe` component is best suited when you need to react to somethin > The `form.Subscribe` component doesn't trigger component-level re-renders. Anytime the value subscribed to changes, only the `form.Subscribe` component re-renders. The choice between whether to use `useSelector` or `form.Subscribe` mainly boils down to your use case. If you're aiming for direct UI updates based on form state, use `form.Subscribe` for its optimization perks. And if you need the reactivity within the logic, then `useSelector` is the better choice. + +## Field state + +Inside a field, you don't need `useSelector` or `form.Subscribe` to read the field's own state. `form.Field` subscribes to its field for you: its render function runs again whenever the field's value or meta (such as `isTouched`, `isDirty`, `errors` or `isValidating`) changes, so `field.state.value` and `field.state.meta` are up to date there. + +The same applies to field components that read the field with `useFieldContext`, as shown in [Form Composition](./form-composition.md#pre-bound-field-components). Even though they live outside the render function, they re-render together with the field, so they can read `field.state.value` and `field.state.meta` directly. + +> Array fields (`mode="array"`) are an exception: to avoid re-rendering the whole list on every keystroke, they don't re-render when a value inside one of their items changes. Render those values with their own `form.Field` instead. + +`useSelector` also accepts a field's store, if you prefer to subscribe to a specific piece of field state: + +```tsx +import { useSelector } from '@tanstack/react-form' + +const errors = useSelector(field.store, (state) => state.meta.errors) +``` From 6ef186f37321924a7e4133e2a3aed678fbe8b62d Mon Sep 17 00:00:00 2001 From: Diogo Esteves Date: Sun, 25 Oct 2026 00:49:50 +0100 Subject: [PATCH 2/3] Update docs/framework/react/guides/reactivity.md Co-authored-by: LeCarbonator <18158911+LeCarbonator@users.noreply.github.com> --- docs/framework/react/guides/reactivity.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/framework/react/guides/reactivity.md b/docs/framework/react/guides/reactivity.md index 5a0f638e3c..6e66388894 100644 --- a/docs/framework/react/guides/reactivity.md +++ b/docs/framework/react/guides/reactivity.md @@ -61,6 +61,7 @@ Inside a field, you don't need `useSelector` or `form.Subscribe` to read the fie The same applies to field components that read the field with `useFieldContext`, as shown in [Form Composition](./form-composition.md#pre-bound-field-components). Even though they live outside the render function, they re-render together with the field, so they can read `field.state.value` and `field.state.meta` directly. +> [!NOTE] > Array fields (`mode="array"`) are an exception: to avoid re-rendering the whole list on every keystroke, they don't re-render when a value inside one of their items changes. Render those values with their own `form.Field` instead. `useSelector` also accepts a field's store, if you prefer to subscribe to a specific piece of field state: From ebdd2bc4b2e60f5fd5c8cc65e3d0b82fc9581b98 Mon Sep 17 00:00:00 2001 From: Diogo Esteves Date: Sun, 25 Oct 2026 00:51:11 +0100 Subject: [PATCH 3/3] docs(react): recommend useSelector in field components --- docs/framework/react/guides/form-composition.md | 8 ++++---- docs/framework/react/guides/reactivity.md | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/framework/react/guides/form-composition.md b/docs/framework/react/guides/form-composition.md index c84e6a4307..0e7513aa47 100644 --- a/docs/framework/react/guides/form-composition.md +++ b/docs/framework/react/guides/form-composition.md @@ -55,11 +55,13 @@ Once this scaffolding is in place, you can start adding custom field and form co > Note: the `useFieldContext` must be the same one exported from your custom form context ```tsx +import { useSelector } from '@tanstack/react-form' import { useFieldContext } from './form-context.tsx' export function TextField({ label }: { label: string }) { // The `Field` infers that it should have a `value` type of `string` const field = useFieldContext() + const errors = useSelector(field.store, (state) => state.meta.errors) return ( ) } ``` -The component re-renders whenever the field's value or meta changes, so `field.state` is always up to date here. See [Reactivity](./reactivity.md#field-state) for details. +To keep a field component in sync with meta such as `errors`, read it with `useSelector`. See [Reactivity](./reactivity.md#field-state) for details. You're then able to register this component with your form hook. diff --git a/docs/framework/react/guides/reactivity.md b/docs/framework/react/guides/reactivity.md index 6e66388894..c857b0a9d8 100644 --- a/docs/framework/react/guides/reactivity.md +++ b/docs/framework/react/guides/reactivity.md @@ -59,12 +59,10 @@ The choice between whether to use `useSelector` or `form.Subscribe` mainly boils Inside a field, you don't need `useSelector` or `form.Subscribe` to read the field's own state. `form.Field` subscribes to its field for you: its render function runs again whenever the field's value or meta (such as `isTouched`, `isDirty`, `errors` or `isValidating`) changes, so `field.state.value` and `field.state.meta` are up to date there. -The same applies to field components that read the field with `useFieldContext`, as shown in [Form Composition](./form-composition.md#pre-bound-field-components). Even though they live outside the render function, they re-render together with the field, so they can read `field.state.value` and `field.state.meta` directly. - > [!NOTE] > Array fields (`mode="array"`) are an exception: to avoid re-rendering the whole list on every keystroke, they don't re-render when a value inside one of their items changes. Render those values with their own `form.Field` instead. -`useSelector` also accepts a field's store, if you prefer to subscribe to a specific piece of field state: +Field components that read the field with `useFieldContext`, as shown in [Form Composition](./form-composition.md#pre-bound-field-components), live outside that render function. In those components, read field state such as `meta` with `useSelector` and the field's store: ```tsx import { useSelector } from '@tanstack/react-form'