diff --git a/packages/preact-form/CHANGELOG.md b/packages/preact-form/CHANGELOG.md
index b0acc92c8..3adefbaa7 100644
--- a/packages/preact-form/CHANGELOG.md
+++ b/packages/preact-form/CHANGELOG.md
@@ -1,5 +1,11 @@
# @tanstack/preact-form
+## 1.30.1
+
+### Patch Changes
+
+- Re-export `useSelector` from `@tanstack/preact-store` (fixes [#2203](https://github.com/TanStack/form/issues/2203)). `useStore` remains available but is deprecated.
+
## 1.30.0
### Minor Changes
diff --git a/packages/preact-form/src/index.ts b/packages/preact-form/src/index.ts
index 56dd2c4d5..fca911b5a 100644
--- a/packages/preact-form/src/index.ts
+++ b/packages/preact-form/src/index.ts
@@ -1,6 +1,6 @@
export * from '@tanstack/form-core'
-export { useStore } from '@tanstack/preact-store'
+export { useSelector, useStore } from '@tanstack/preact-store'
export * from './createFormHook'
export * from './types'
diff --git a/packages/preact-form/src/useField.tsx b/packages/preact-form/src/useField.tsx
index 3c74c7747..256e9d53b 100644
--- a/packages/preact-form/src/useField.tsx
+++ b/packages/preact-form/src/useField.tsx
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'preact/hooks'
import { FieldApi, functionalUpdate } from '@tanstack/form-core'
-import { useStore } from '@tanstack/preact-store'
+import { useSelector } from '@tanstack/preact-store'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
AnyFieldApi,
@@ -188,7 +188,7 @@ export function useField<
// For array mode, only track length changes to avoid re-renders when child properties change
// See: https://github.com/TanStack/form/issues/1925
- const reactiveStateValue = useStore(
+ const reactiveStateValue = useSelector(
fieldApi.store,
(opts.mode === 'array'
? (state) => state.meta._arrayVersion || 0
@@ -196,27 +196,27 @@ export function useField<
state: typeof fieldApi.state,
) => TData | number,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
fieldApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
fieldApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
fieldApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
fieldApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
fieldApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
fieldApi.store,
(state) => state.meta.isValidating,
)
diff --git a/packages/preact-form/src/useFieldGroup.tsx b/packages/preact-form/src/useFieldGroup.tsx
index f81f35b12..0e0478920 100644
--- a/packages/preact-form/src/useFieldGroup.tsx
+++ b/packages/preact-form/src/useFieldGroup.tsx
@@ -1,6 +1,6 @@
import { useState } from 'preact/hooks'
import { FieldGroupApi, functionalUpdate } from '@tanstack/form-core'
-import { useStore } from '@tanstack/preact-store'
+import { useSelector } from '@tanstack/preact-store'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
AnyFieldGroupApi,
@@ -23,7 +23,7 @@ function LocalSubscribe({
lens: AnyFieldGroupApi
selector: (state: FieldGroupState
) => FieldGroupState
}>): ReturnType {
- const data = useStore(lens.store, selector)
+ const data = useSelector(lens.store, selector)
return <>{functionalUpdate(children, data)}>
}
diff --git a/packages/preact-form/src/useForm.tsx b/packages/preact-form/src/useForm.tsx
index dcf8f7660..ca50d07d4 100644
--- a/packages/preact-form/src/useForm.tsx
+++ b/packages/preact-form/src/useForm.tsx
@@ -1,6 +1,6 @@
import { FormApi, functionalUpdate, mergeAndUpdate } from '@tanstack/form-core'
import { useMemo, useRef, useState } from 'preact/hooks'
-import { useStore } from '@tanstack/preact-store'
+import { useSelector } from '@tanstack/preact-store'
import { Field } from './useField'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import { useFormId } from './useFormId'
@@ -160,7 +160,7 @@ function LocalSubscribe({
form: AnyFormApi
selector: (state: AnyFormState) => AnyFormState
}>): ReturnType {
- const data = useStore(form.store, selector)
+ const data = useSelector(form.store, selector)
return <>{functionalUpdate(children, data)}>
}
diff --git a/packages/preact-form/src/useFormGroup.tsx b/packages/preact-form/src/useFormGroup.tsx
index d8a15dd8a..3cd22d6a0 100644
--- a/packages/preact-form/src/useFormGroup.tsx
+++ b/packages/preact-form/src/useFormGroup.tsx
@@ -1,5 +1,5 @@
import { useMemo, useState } from 'preact/hooks'
-import { useStore } from '@tanstack/preact-store'
+import { useSelector } from '@tanstack/preact-store'
import { FormGroupApi, functionalUpdate } from '@tanstack/form-core'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
@@ -201,71 +201,71 @@ export function useFormGroup<
setPrevOptions({ form: opts.form, name: opts.name })
}
- const reactiveStateValue = useStore(
+ const reactiveStateValue = useSelector(
formGroupApi.store,
(state) => state.value,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
formGroupApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
formGroupApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
formGroupApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
formGroupApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
formGroupApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
formGroupApi.store,
(state) => state.meta.isValidating,
)
// Submission lifecycle and aggregated validity now live on `state.meta`
// (mirroring `FieldApi.state.meta`).
- const reactiveMetaIsSubmitting = useStore(
+ const reactiveMetaIsSubmitting = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitting,
)
- const reactiveMetaIsSubmitted = useStore(
+ const reactiveMetaIsSubmitted = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitted,
)
- const reactiveMetaSubmissionAttempts = useStore(
+ const reactiveMetaSubmissionAttempts = useSelector(
formGroupApi.store,
(state) => state.meta.submissionAttempts,
)
- const reactiveMetaIsSubmitSuccessful = useStore(
+ const reactiveMetaIsSubmitSuccessful = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitSuccessful,
)
- const reactiveMetaCanSubmit = useStore(
+ const reactiveMetaCanSubmit = useSelector(
formGroupApi.store,
(state) => state.meta.canSubmit,
)
- const reactiveMetaIsValid = useStore(
+ const reactiveMetaIsValid = useSelector(
formGroupApi.store,
(state) => state.meta.isValid,
)
- const reactiveMetaIsFieldsValid = useStore(
+ const reactiveMetaIsFieldsValid = useSelector(
formGroupApi.store,
(state) => state.meta.isFieldsValid,
)
- const reactiveMetaIsFieldsValidating = useStore(
+ const reactiveMetaIsFieldsValidating = useSelector(
formGroupApi.store,
(state) => state.meta.isFieldsValidating,
)
- const reactiveMetaIsGroupValid = useStore(
+ const reactiveMetaIsGroupValid = useSelector(
formGroupApi.store,
(state) => state.meta.isGroupValid,
)
diff --git a/packages/react-form/CHANGELOG.md b/packages/react-form/CHANGELOG.md
index c7e0bc7c5..719121012 100644
--- a/packages/react-form/CHANGELOG.md
+++ b/packages/react-form/CHANGELOG.md
@@ -1,5 +1,11 @@
# @tanstack/react-form
+## 1.33.1
+
+### Patch Changes
+
+- Re-export `useSelector` from `@tanstack/react-store` (fixes [#2203](https://github.com/TanStack/form/issues/2203)). `useStore` remains available but is deprecated; prefer `import { useSelector } from '@tanstack/react-form'`.
+
## 1.33.0
### Minor Changes
diff --git a/packages/react-form/src/index.ts b/packages/react-form/src/index.ts
index 604315884..e6aa1055b 100644
--- a/packages/react-form/src/index.ts
+++ b/packages/react-form/src/index.ts
@@ -1,6 +1,6 @@
export * from '@tanstack/form-core'
-export { useStore } from '@tanstack/react-store'
+export { useSelector, useStore } from '@tanstack/react-store'
export * from './createFormHook'
export * from './types'
diff --git a/packages/react-form/src/useField.tsx b/packages/react-form/src/useField.tsx
index a2b9241ea..b0d3eff9f 100644
--- a/packages/react-form/src/useField.tsx
+++ b/packages/react-form/src/useField.tsx
@@ -1,7 +1,7 @@
'use client'
import { useMemo, useState } from 'react'
-import { useStore } from '@tanstack/react-store'
+import { useSelector } from '@tanstack/react-store'
import { FieldApi, functionalUpdate } from '@tanstack/form-core'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
@@ -190,7 +190,7 @@ export function useField<
// For array mode, only track length changes to avoid re-renders when child properties change
// See: https://github.com/TanStack/form/issues/1925
- const reactiveStateValue = useStore(
+ const reactiveStateValue = useSelector(
fieldApi.store,
(opts.mode === 'array'
? (state) => state.meta._arrayVersion || 0
@@ -198,27 +198,27 @@ export function useField<
state: typeof fieldApi.state,
) => TData | number,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
fieldApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
fieldApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
fieldApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
fieldApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
fieldApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
fieldApi.store,
(state) => state.meta.isValidating,
)
diff --git a/packages/react-form/src/useFieldGroup.tsx b/packages/react-form/src/useFieldGroup.tsx
index a3e05df9f..dc6d4d1a3 100644
--- a/packages/react-form/src/useFieldGroup.tsx
+++ b/packages/react-form/src/useFieldGroup.tsx
@@ -1,7 +1,7 @@
'use client'
import { useState } from 'react'
-import { useStore } from '@tanstack/react-store'
+import { useSelector } from '@tanstack/react-store'
import { FieldGroupApi, functionalUpdate } from '@tanstack/form-core'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
@@ -29,7 +29,7 @@ function LocalSubscribe({
lens: AnyFieldGroupApi
selector?: (state: FieldGroupState) => FieldGroupState
}>): ReturnType {
- const data = useStore(lens.store, selector)
+ const data = useSelector(lens.store, selector)
return <>{functionalUpdate(children, data)}>
}
diff --git a/packages/react-form/src/useForm.tsx b/packages/react-form/src/useForm.tsx
index 1b11566f5..2b898adca 100644
--- a/packages/react-form/src/useForm.tsx
+++ b/packages/react-form/src/useForm.tsx
@@ -1,7 +1,7 @@
'use client'
import { FormApi, functionalUpdate, mergeAndUpdate } from '@tanstack/form-core'
-import { useStore } from '@tanstack/react-store'
+import { useSelector } from '@tanstack/react-store'
import { useMemo, useRef, useState } from 'react'
import { Field } from './useField'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
@@ -161,7 +161,7 @@ function LocalSubscribe({
form: AnyFormApi
selector?: (state: AnyFormState) => AnyFormState
}>): ReturnType {
- const data = useStore(form.store, selector)
+ const data = useSelector(form.store, selector)
return <>{functionalUpdate(children, data)}>
}
diff --git a/packages/react-form/src/useFormGroup.tsx b/packages/react-form/src/useFormGroup.tsx
index 41c2fe97c..d9d02f498 100644
--- a/packages/react-form/src/useFormGroup.tsx
+++ b/packages/react-form/src/useFormGroup.tsx
@@ -1,7 +1,7 @@
'use client'
import { useMemo, useState } from 'react'
-import { useStore } from '@tanstack/react-store'
+import { useSelector } from '@tanstack/react-store'
import { FormGroupApi, functionalUpdate } from '@tanstack/form-core'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import type {
@@ -203,32 +203,32 @@ export function useFormGroup<
setPrevOptions({ form: opts.form, name: opts.name })
}
- const reactiveStateValue = useStore(
+ const reactiveStateValue = useSelector(
formGroupApi.store,
(state) => state.value,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
formGroupApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
formGroupApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
formGroupApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
formGroupApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
formGroupApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
formGroupApi.store,
(state) => state.meta.isValidating,
)
@@ -236,39 +236,39 @@ export function useFormGroup<
// Submission lifecycle and aggregated validity now live on `state.meta`
// (mirroring `FieldApi.state.meta`). Subscribe to the fields callers
// typically read so React Compiler picks them up as dependencies.
- const reactiveMetaIsSubmitting = useStore(
+ const reactiveMetaIsSubmitting = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitting,
)
- const reactiveMetaIsSubmitted = useStore(
+ const reactiveMetaIsSubmitted = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitted,
)
- const reactiveMetaSubmissionAttempts = useStore(
+ const reactiveMetaSubmissionAttempts = useSelector(
formGroupApi.store,
(state) => state.meta.submissionAttempts,
)
- const reactiveMetaIsSubmitSuccessful = useStore(
+ const reactiveMetaIsSubmitSuccessful = useSelector(
formGroupApi.store,
(state) => state.meta.isSubmitSuccessful,
)
- const reactiveMetaCanSubmit = useStore(
+ const reactiveMetaCanSubmit = useSelector(
formGroupApi.store,
(state) => state.meta.canSubmit,
)
- const reactiveMetaIsValid = useStore(
+ const reactiveMetaIsValid = useSelector(
formGroupApi.store,
(state) => state.meta.isValid,
)
- const reactiveMetaIsFieldsValid = useStore(
+ const reactiveMetaIsFieldsValid = useSelector(
formGroupApi.store,
(state) => state.meta.isFieldsValid,
)
- const reactiveMetaIsFieldsValidating = useStore(
+ const reactiveMetaIsFieldsValidating = useSelector(
formGroupApi.store,
(state) => state.meta.isFieldsValidating,
)
- const reactiveMetaIsGroupValid = useStore(
+ const reactiveMetaIsGroupValid = useSelector(
formGroupApi.store,
(state) => state.meta.isGroupValid,
)
diff --git a/packages/react-form/tests/exports.test.ts b/packages/react-form/tests/exports.test.ts
new file mode 100644
index 000000000..360eba628
--- /dev/null
+++ b/packages/react-form/tests/exports.test.ts
@@ -0,0 +1,9 @@
+import { describe, expect, it } from 'vitest'
+import { useSelector, useStore } from '../src'
+
+describe('package exports', () => {
+ it('exports useSelector and useStore from @tanstack/react-store', () => {
+ expect(useSelector).toBeTypeOf('function')
+ expect(useStore).toBeTypeOf('function')
+ })
+})
diff --git a/packages/solid-form/CHANGELOG.md b/packages/solid-form/CHANGELOG.md
index c6dc2a291..40488d7ac 100644
--- a/packages/solid-form/CHANGELOG.md
+++ b/packages/solid-form/CHANGELOG.md
@@ -1,5 +1,11 @@
# @tanstack/solid-form
+## 1.33.1
+
+### Patch Changes
+
+- Re-export `useSelector` from `@tanstack/solid-store`. Add `form.useSelector`; `form.useStore` is deprecated (fixes [#2203](https://github.com/TanStack/form/issues/2203)).
+
## 1.33.0
### Minor Changes
diff --git a/packages/solid-form/src/createField.tsx b/packages/solid-form/src/createField.tsx
index 373146864..ade0ec17b 100644
--- a/packages/solid-form/src/createField.tsx
+++ b/packages/solid-form/src/createField.tsx
@@ -6,7 +6,7 @@ import {
onCleanup,
onMount,
} from 'solid-js'
-import { useStore } from '@tanstack/solid-store'
+import { useSelector } from '@tanstack/solid-store'
import type {
DeepKeys,
DeepValue,
@@ -173,30 +173,30 @@ function makeFieldReactive<
// avoid re-renders when child properties change. Meta is tracked piece by
// piece so that consumers re-render when any meta property updates.
// See: https://github.com/TanStack/form/issues/1961
- const reactiveStateValue = useStore(fieldApi.store, (state) =>
+ const reactiveStateValue = useSelector(fieldApi.store, (state) =>
mode === 'array' ? state.meta._arrayVersion || 0 : state.value,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
fieldApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
fieldApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
fieldApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
fieldApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
fieldApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
fieldApi.store,
(state) => state.meta.isValidating,
)
diff --git a/packages/solid-form/src/createFieldGroup.tsx b/packages/solid-form/src/createFieldGroup.tsx
index 0310dd9d9..6d32b2d55 100644
--- a/packages/solid-form/src/createFieldGroup.tsx
+++ b/packages/solid-form/src/createFieldGroup.tsx
@@ -1,5 +1,5 @@
import { FieldGroupApi, functionalUpdate } from '@tanstack/form-core'
-import { useStore } from '@tanstack/solid-store'
+import { useSelector } from '@tanstack/solid-store'
import { onCleanup, onMount } from 'solid-js'
import type { Component, JSX, ParentProps } from 'solid-js'
import type {
@@ -201,7 +201,7 @@ export function createFieldGroup<
)
extendedApi.Subscribe = (props) => {
- const data = useStore(api.store, props.selector)
+ const data = useSelector(api.store, props.selector)
return functionalUpdate(props.children, data()) as Element
}
diff --git a/packages/solid-form/src/createForm.tsx b/packages/solid-form/src/createForm.tsx
index 844dfa833..01a216412 100644
--- a/packages/solid-form/src/createForm.tsx
+++ b/packages/solid-form/src/createForm.tsx
@@ -1,6 +1,6 @@
import { FormApi, functionalUpdate } from '@tanstack/form-core'
import { createComputed, onMount } from 'solid-js'
-import { useStore } from '@tanstack/solid-store'
+import { useSelector } from '@tanstack/solid-store'
import { Field, createField } from './createField'
import { FormGroup } from './createFormGroup'
import type {
@@ -55,6 +55,44 @@ export interface SolidFormApi<
TFormOnServer,
TSubmitMeta
>
+ useSelector: <
+ TSelected = NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ >(
+ selector?: (
+ state: NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ ) => TSelected,
+ ) => () => TSelected
+ /**
+ * @deprecated Use `form.useSelector` instead.
+ */
useStore: <
TSelected = NoInfer<
FormState<
@@ -234,9 +272,11 @@ export function createForm<
extendedApi.Field = (props) =>
extendedApi.FormGroup = (props) =>
- extendedApi.useStore = (selector) => useStore(api.store, selector)
+ extendedApi.useSelector = (selector) => useSelector(api.store, selector)
+ /** @deprecated Use `form.useSelector` instead. */
+ extendedApi.useStore = extendedApi.useSelector
extendedApi.Subscribe = (props) =>
- functionalUpdate(props.children, useStore(api.store, props.selector))
+ functionalUpdate(props.children, useSelector(api.store, props.selector))
onMount(api.mount)
diff --git a/packages/solid-form/src/createFormGroup.tsx b/packages/solid-form/src/createFormGroup.tsx
index 47467a88a..dd6d89ebd 100644
--- a/packages/solid-form/src/createFormGroup.tsx
+++ b/packages/solid-form/src/createFormGroup.tsx
@@ -6,7 +6,7 @@ import {
onCleanup,
onMount,
} from 'solid-js'
-import { useStore } from '@tanstack/solid-store'
+import { useSelector } from '@tanstack/solid-store'
import type {
DeepKeys,
DeepValue,
@@ -114,7 +114,7 @@ function makeFormGroupReactive<
> {
const [group, setGroup] = createSignal(formGroupApi, { equals: false })
// Handle shallow comparison to make sure that Derived doesn't create a new setGroup call every time
- const store = useStore(formGroupApi.store, (store) => store)
+ const store = useSelector(formGroupApi.store, (store) => store)
// Run before initial render
createComputed(() => {
// Use the store to track dependencies
diff --git a/packages/solid-form/src/index.tsx b/packages/solid-form/src/index.tsx
index 185487856..aa54e2927 100644
--- a/packages/solid-form/src/index.tsx
+++ b/packages/solid-form/src/index.tsx
@@ -1,6 +1,6 @@
export * from '@tanstack/form-core'
-export { useStore } from '@tanstack/solid-store'
+export { useSelector, useStore } from '@tanstack/solid-store'
export * from './createField'
export * from './createForm'
diff --git a/packages/svelte-form/CHANGELOG.md b/packages/svelte-form/CHANGELOG.md
index 03a75e108..3b5a0a18c 100644
--- a/packages/svelte-form/CHANGELOG.md
+++ b/packages/svelte-form/CHANGELOG.md
@@ -1,5 +1,11 @@
# @tanstack/svelte-form
+## 1.33.1
+
+### Patch Changes
+
+- Re-export `useSelector` from `@tanstack/svelte-store`. Add `form.useSelector`; `form.useStore` is deprecated (fixes [#2203](https://github.com/TanStack/form/issues/2203)).
+
## 1.33.0
### Minor Changes
diff --git a/packages/svelte-form/src/Field.svelte b/packages/svelte-form/src/Field.svelte
index bf1362964..239f7592a 100644
--- a/packages/svelte-form/src/Field.svelte
+++ b/packages/svelte-form/src/Field.svelte
@@ -8,7 +8,7 @@
type FormAsyncValidateOrFn,
type FormValidateOrFn,
} from '@tanstack/form-core'
- import { useStore } from '@tanstack/svelte-store'
+ import { useSelector } from '@tanstack/svelte-store'
import { onMount, type Snippet } from 'svelte'
import type { CreateFieldOptions } from './types.js'
@@ -96,26 +96,26 @@
api.update(current)
})
- const storeSub = useStore(api.store, (state) =>
+ const storeSub = useSelector(api.store, (state) =>
options.mode === 'array'
? state.meta._arrayVersion || 0
: state.value,
)
- const metaIsTouchedSub = useStore(
+ const metaIsTouchedSub = useSelector(
api.store,
(state) => state.meta.isTouched,
)
- const metaIsBlurredSub = useStore(
+ const metaIsBlurredSub = useSelector(
api.store,
(state) => state.meta.isBlurred,
)
- const metaIsDirtySub = useStore(api.store, (state) => state.meta.isDirty)
- const metaErrorMapSub = useStore(api.store, (state) => state.meta.errorMap)
- const metaErrorSourceMapSub = useStore(
+ const metaIsDirtySub = useSelector(api.store, (state) => state.meta.isDirty)
+ const metaErrorMapSub = useSelector(api.store, (state) => state.meta.errorMap)
+ const metaErrorSourceMapSub = useSelector(
api.store,
(state) => state.meta.errorSourceMap,
)
- const metaIsValidatingSub = useStore(
+ const metaIsValidatingSub = useSelector(
api.store,
(state) => state.meta.isValidating,
)
diff --git a/packages/svelte-form/src/FormGroup.svelte b/packages/svelte-form/src/FormGroup.svelte
index dcf4e8710..919bf43fc 100644
--- a/packages/svelte-form/src/FormGroup.svelte
+++ b/packages/svelte-form/src/FormGroup.svelte
@@ -9,7 +9,7 @@
type FormAsyncValidateOrFn,
type FormValidateOrFn,
} from '@tanstack/form-core'
- import { useStore } from '@tanstack/svelte-store'
+ import { useSelector } from '@tanstack/svelte-store'
import { onMount, type Snippet } from 'svelte'
export function createFormGroup<
@@ -108,7 +108,7 @@
api.update(current)
})
- const storeSub = useStore(api.store)
+ const storeSub = useSelector(api.store)
Object.defineProperty(extendedApi, 'state', {
get() {
return storeSub.current
diff --git a/packages/svelte-form/src/Subscribe.svelte b/packages/svelte-form/src/Subscribe.svelte
index 4f5f255a2..8f12a11e6 100644
--- a/packages/svelte-form/src/Subscribe.svelte
+++ b/packages/svelte-form/src/Subscribe.svelte
@@ -1,5 +1,5 @@
{@render children(value.current)}
diff --git a/packages/svelte-form/src/createForm.svelte.ts b/packages/svelte-form/src/createForm.svelte.ts
index 9f40d71ba..1b40ce748 100644
--- a/packages/svelte-form/src/createForm.svelte.ts
+++ b/packages/svelte-form/src/createForm.svelte.ts
@@ -1,5 +1,5 @@
import { FormApi } from '@tanstack/form-core'
-import { useStore } from '@tanstack/svelte-store'
+import { useSelector } from '@tanstack/svelte-store'
import { onMount } from 'svelte'
import Field from './Field.svelte'
import FormGroup from './FormGroup.svelte'
@@ -64,6 +64,44 @@ export interface SvelteFormApi<
TFormOnServer,
TSubmitMeta
>
+ useSelector: <
+ TSelected = NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ >(
+ selector?: (
+ state: NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ ) => TSelected,
+ ) => { current: TSelected }
+ /**
+ * @deprecated Use `form.useSelector` instead.
+ */
useStore: <
TSelected = NoInfer<
FormState<
@@ -295,7 +333,9 @@ export function createForm<
// @ts-expect-error constructor definition exists only on a type level
extendedApi.FormGroup = (internal, props) =>
FormGroup(internal, { ...props, form: api as never } as never)
- extendedApi.useStore = (selector) => useStore(api.store, selector)
+ extendedApi.useSelector = (selector) => useSelector(api.store, selector)
+ /** @deprecated Use `form.useSelector` instead. */
+ extendedApi.useStore = extendedApi.useSelector
// @ts-expect-error constructor definition exists only on a type level
extendedApi.Subscribe = (internal, props) =>
Subscribe(internal, { ...props, store: api.store })
diff --git a/packages/svelte-form/src/index.ts b/packages/svelte-form/src/index.ts
index 115aa4468..6a2f680bd 100644
--- a/packages/svelte-form/src/index.ts
+++ b/packages/svelte-form/src/index.ts
@@ -1,6 +1,6 @@
export * from '@tanstack/form-core'
-export { useStore } from '@tanstack/svelte-store'
+export { useSelector, useStore } from '@tanstack/svelte-store'
export { createForm, type SvelteFormApi } from './createForm.svelte.js'
diff --git a/packages/vue-form/CHANGELOG.md b/packages/vue-form/CHANGELOG.md
index cb49c47a1..07edbad34 100644
--- a/packages/vue-form/CHANGELOG.md
+++ b/packages/vue-form/CHANGELOG.md
@@ -1,5 +1,11 @@
# @tanstack/vue-form
+## 1.33.1
+
+### Patch Changes
+
+- Re-export `useSelector` from `@tanstack/vue-store`. Add `form.useSelector`; `form.useStore` is deprecated (fixes [#2203](https://github.com/TanStack/form/issues/2203)).
+
## 1.33.0
### Minor Changes
diff --git a/packages/vue-form/src/index.ts b/packages/vue-form/src/index.ts
index 071eb7d06..f254b398e 100644
--- a/packages/vue-form/src/index.ts
+++ b/packages/vue-form/src/index.ts
@@ -1,5 +1,5 @@
export * from '@tanstack/form-core'
-export { useStore } from '@tanstack/vue-store'
+export { useSelector, useStore } from '@tanstack/vue-store'
export * from './useField'
export * from './useForm'
export * from './useFormGroup'
diff --git a/packages/vue-form/src/useField.tsx b/packages/vue-form/src/useField.tsx
index 599154839..1d1031d94 100644
--- a/packages/vue-form/src/useField.tsx
+++ b/packages/vue-form/src/useField.tsx
@@ -1,5 +1,5 @@
import { FieldApi } from '@tanstack/form-core'
-import { useStore } from '@tanstack/vue-store'
+import { useSelector } from '@tanstack/vue-store'
import { computed, defineComponent, onMounted, onUnmounted, watch } from 'vue'
import type {
AnyFieldApi,
@@ -257,7 +257,7 @@ export function useField<
// For array mode, only track length changes to avoid re-renders when child properties change
// See: https://github.com/TanStack/form/issues/1925
- const reactiveStateValue = useStore(
+ const reactiveStateValue = useSelector(
fieldApi.store,
(opts.mode === 'array'
? (state) => state.meta._arrayVersion || 0
@@ -265,27 +265,27 @@ export function useField<
state: typeof fieldApi.state,
) => TData | number,
)
- const reactiveMetaIsTouched = useStore(
+ const reactiveMetaIsTouched = useSelector(
fieldApi.store,
(state) => state.meta.isTouched,
)
- const reactiveMetaIsBlurred = useStore(
+ const reactiveMetaIsBlurred = useSelector(
fieldApi.store,
(state) => state.meta.isBlurred,
)
- const reactiveMetaIsDirty = useStore(
+ const reactiveMetaIsDirty = useSelector(
fieldApi.store,
(state) => state.meta.isDirty,
)
- const reactiveMetaErrorMap = useStore(
+ const reactiveMetaErrorMap = useSelector(
fieldApi.store,
(state) => state.meta.errorMap,
)
- const reactiveMetaErrorSourceMap = useStore(
+ const reactiveMetaErrorSourceMap = useSelector(
fieldApi.store,
(state) => state.meta.errorSourceMap,
)
- const reactiveMetaIsValidating = useStore(
+ const reactiveMetaIsValidating = useSelector(
fieldApi.store,
(state) => state.meta.isValidating,
)
diff --git a/packages/vue-form/src/useForm.tsx b/packages/vue-form/src/useForm.tsx
index 63d93e838..43b434779 100644
--- a/packages/vue-form/src/useForm.tsx
+++ b/packages/vue-form/src/useForm.tsx
@@ -1,5 +1,5 @@
import { FormApi } from '@tanstack/form-core'
-import { useStore } from '@tanstack/vue-store'
+import { useSelector } from '@tanstack/vue-store'
import { defineComponent, h, onMounted } from 'vue'
import { Field } from './useField'
import { FormGroup } from './useFormGroup'
@@ -151,6 +151,44 @@ export interface VueFormApi<
TFormOnServer,
TSubmitMeta
>
+ useSelector: <
+ TSelected = NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ >(
+ selector?: (
+ state: NoInfer<
+ FormState<
+ TParentData,
+ TFormOnMount,
+ TFormOnChange,
+ TFormOnChangeAsync,
+ TFormOnBlur,
+ TFormOnBlurAsync,
+ TFormOnSubmit,
+ TFormOnSubmitAsync,
+ TFormOnDynamic,
+ TFormOnDynamicAsync,
+ TFormOnServer
+ >
+ >,
+ ) => TSelected,
+ ) => Readonly[>
+ /**
+ * @deprecated Use `form.useSelector` instead.
+ */
useStore: <
TSelected = NoInfer<
FormState<
@@ -289,14 +327,16 @@ export function useForm<
inheritAttrs: false,
},
) as never
- extendedApi.useStore = (selector) => {
- return useStore(api.store as never, selector as never) as never
- }
+ const subscribeToStore = (selector?: (state: never) => unknown) =>
+ useSelector(api.store as never, selector as never) as never
+ extendedApi.useSelector = subscribeToStore
+ /** @deprecated Use `form.useSelector` instead. */
+ extendedApi.useStore = subscribeToStore
extendedApi.Subscribe = defineComponent(
(props, context) => {
const allProps = { ...props, ...context.attrs }
const selector = allProps.selector ?? ((state: never) => state)
- const data = useStore(api.store as never, selector as never)
+ const data = useSelector(api.store as never, selector as never)
return () => context.slots.default!(data.value)
},
{
diff --git a/packages/vue-form/src/useFormGroup.tsx b/packages/vue-form/src/useFormGroup.tsx
index 105ea321b..f0ab50ab2 100644
--- a/packages/vue-form/src/useFormGroup.tsx
+++ b/packages/vue-form/src/useFormGroup.tsx
@@ -1,5 +1,5 @@
import { FormGroupApi } from '@tanstack/form-core'
-import { useStore } from '@tanstack/vue-store'
+import { useSelector } from '@tanstack/vue-store'
import { defineComponent, onMounted, onUnmounted, watch } from 'vue'
import type {
DeepKeys,
@@ -293,7 +293,7 @@ export function useFormGroup<
return api
})()
- const groupState = useStore(formGroupApi.store, (state) => state)
+ const groupState = useSelector(formGroupApi.store, (state) => state)
let cleanup!: () => void
onMounted(() => {
From 174ab492427a992ed8c5822f7d841825c769996e Mon Sep 17 00:00:00 2001
From: hemraj-007 <140829250+hemraj-007@users.noreply.github.com>
Date: Thu, 4 Jun 2026 19:59:16 +0530
Subject: [PATCH 2/2] docs(preact): use selector-form useSelector in prose
---
docs/framework/preact/guides/basic-concepts.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/framework/preact/guides/basic-concepts.md b/docs/framework/preact/guides/basic-concepts.md
index c56dbd88e..1b35934d2 100644
--- a/docs/framework/preact/guides/basic-concepts.md
+++ b/docs/framework/preact/guides/basic-concepts.md
@@ -236,7 +236,7 @@ function App() {
## Reactivity
-`@tanstack/preact-form` offers various ways to subscribe to form and field state changes, most notably the `useSelector(form.store)` hook and the `form.Subscribe` component. These methods allow you to optimize your form's rendering performance by only updating components when necessary.
+`@tanstack/preact-form` offers various ways to subscribe to form and field state changes, most notably the `useSelector(form.store, …)` hook and the `form.Subscribe` component. These methods allow you to optimize your form's rendering performance by only updating components when necessary.
Example:
@@ -265,7 +265,7 @@ const errors = useSelector(form.store, (state) => state.errorMap)
const store = useSelector(form.store)
```
-Note: The usage of the `useField` hook to achieve reactivity is discouraged since it is designed to be used thoughtfully within the `form.Field` component. You might want to use `useSelector(form.store)` instead.
+Note: The usage of the `useField` hook to achieve reactivity is discouraged since it is designed to be used thoughtfully within the `form.Field` component. You might want to use `useSelector(form.store, …)` instead.
## Listeners
]