diff --git a/packages/react-form/src/index.ts b/packages/react-form/src/index.ts index e032da0e2..c5878a608 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 { useStore } from './useStore' export * from './createFormHook' export * from './types' diff --git a/packages/react-form/src/useStore.ts b/packages/react-form/src/useStore.ts new file mode 100644 index 000000000..34276c73a --- /dev/null +++ b/packages/react-form/src/useStore.ts @@ -0,0 +1,44 @@ +import { useStore as _useStore } from '@tanstack/react-store' +import type { AnyAtom } from '@tanstack/react-store' + +type AtomSnapshot = TAtom extends { get: () => infer TSnapshot } + ? TSnapshot + : undefined + +/** + * Subscribe to a store atom and return its current state. + * + * When called without a `selector` the full atom snapshot is returned. + * + * @example + * // Return the full form state (selector optional for back-compat) + * const formState = useStore(form.store) + * + * @example + * // Return a specific slice + * const isValid = useStore(form.store, (s) => s.isValid) + */ +export function useStore( + atom: TAtom, +): AtomSnapshot + +export function useStore( + atom: TAtom, + selector: (snapshot: AtomSnapshot) => T, + compare?: (a: T, b: T) => boolean, +): T + +export function useStore( + atom: TAtom, + selector?: (snapshot: AtomSnapshot) => T, + compare?: (a: T, b: T) => boolean, +): T | AtomSnapshot { + // When no selector is provided fall back to the identity function so that + // callers that were using `useStore(form.store)` without a selector + // (as was valid in prior releases) continue to work. + return _useStore( + atom, + (selector ?? ((s: any) => s)) as (snapshot: AtomSnapshot) => T, + compare, + ) +}