or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced.mdfield-api.mdform-api.mdframework-integrations.mdhooks.mdindex.mdvalidation.md
tile.json

tessl/npm-tanstack--react-form

Powerful, type-safe forms for React.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@tanstack/react-form@1.23.x

To install, run

npx @tessl/cli install tessl/npm-tanstack--react-form@1.23.0

index.mddocs/

TanStack React Form

TanStack React Form is a headless, framework-agnostic form state management library for React applications. It provides powerful type-safe form handling with comprehensive validation support, nested field management, and seamless integration with modern React frameworks. The library offers complete control over UI rendering while managing complex form state, validation lifecycles, and field dependencies internally.

Package Information

  • Package Name: @tanstack/react-form
  • Package Type: npm
  • Language: TypeScript
  • Version: 1.23.7
  • Installation: npm install @tanstack/react-form

Core Imports

import { useForm, useField, useFieldGroup, useStore } from '@tanstack/react-form';
import type { FormApi, FieldApi, FormOptions } from '@tanstack/react-form';

For CommonJS:

const { useForm, useField, useFieldGroup } = require('@tanstack/react-form');

Framework-specific imports:

// Next.js
import { createServerValidate, initialFormState } from '@tanstack/react-form/nextjs';

// Remix
import { createServerValidate, initialFormState } from '@tanstack/react-form/remix';

// TanStack Start
import { createServerValidate, getFormData, initialFormState } from '@tanstack/react-form/start';

Basic Usage

import { useForm } from '@tanstack/react-form';

function MyForm() {
  const form = useForm({
    defaultValues: {
      firstName: '',
      lastName: '',
      email: '',
    },
    onSubmit: async ({ value }) => {
      console.log('Form submitted:', value);
    },
  });

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        form.handleSubmit();
      }}
    >
      <form.Field
        name="firstName"
        validators={{
          onChange: ({ value }) =>
            value.length < 2 ? 'First name must be at least 2 characters' : undefined,
        }}
      >
        {(field) => (
          <div>
            <label htmlFor={field.name}>First Name:</label>
            <input
              id={field.name}
              value={field.state.value}
              onChange={(e) => field.handleChange(e.target.value)}
              onBlur={field.handleBlur}
            />
            {field.state.meta.errors.length > 0 && (
              <em>{field.state.meta.errors[0]}</em>
            )}
          </div>
        )}
      </form.Field>

      <button type="submit" disabled={!form.state.canSubmit}>
        Submit
      </button>
    </form>
  );
}

Architecture

TanStack React Form is built on several core concepts:

  • FormApi: Core form state manager handling validation, submission, and field coordination
  • FieldApi: Individual field state manager with validation and metadata tracking
  • FieldGroupApi: Manages related fields as a logical unit with shared state
  • Store Pattern: Reactive state management using @tanstack/react-store for efficient re-renders
  • Validation System: Supports synchronous/asynchronous validators at form and field levels
  • Schema Integration: Compatible with validation libraries via Standard Schema interface
  • Framework Adapters: Server-side validation for Next.js, Remix, and TanStack Start

Capabilities

Form Management

Create and manage form state with comprehensive validation and submission handling.

function useForm<
  TFormData,
  TOnMount extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnChange extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnBlur extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnSubmit extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnDynamic extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TSubmitMeta = never,
>(
  opts?: FormOptions<
    TFormData,
    TOnMount,
    TOnChange,
    TOnChangeAsync,
    TOnBlur,
    TOnBlurAsync,
    TOnSubmit,
    TOnSubmitAsync,
    TOnDynamic,
    TOnDynamicAsync,
    TOnServer,
    TSubmitMeta
  >,
): ReactFormExtendedApi<
  TFormData,
  TOnMount,
  TOnChange,
  TOnChangeAsync,
  TOnBlur,
  TOnBlurAsync,
  TOnSubmit,
  TOnSubmitAsync,
  TOnDynamic,
  TOnDynamicAsync,
  TOnServer,
  TSubmitMeta
>;

Form Management

Field Management

Manage individual form fields with validation, metadata, and array operations.

function useField<
  TParentData,
  TName extends DeepKeys<TParentData>,
  TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
  TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,
  TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,
  TOnChangeAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,
  TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,
  TOnBlurAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,
  TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,
  TOnSubmitAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,
  TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,
  TOnDynamicAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,
  TFormOnMount extends undefined | FormValidateOrFn<TParentData> = undefined,
  TFormOnChange extends undefined | FormValidateOrFn<TParentData> = undefined,
  TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,
  TFormOnBlur extends undefined | FormValidateOrFn<TParentData> = undefined,
  TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,
  TFormOnSubmit extends undefined | FormValidateOrFn<TParentData> = undefined,
  TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,
  TFormOnDynamic extends undefined | FormValidateOrFn<TParentData> = undefined,
  TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,
  TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,
  TParentSubmitMeta = never,
>(
  opts: UseFieldOptions<
    TParentData,
    TName,
    TData,
    TOnMount,
    TOnChange,
    TOnChangeAsync,
    TOnBlur,
    TOnBlurAsync,
    TOnSubmit,
    TOnSubmitAsync,
    TOnDynamic,
    TOnDynamicAsync,
    TFormOnMount,
    TFormOnChange,
    TFormOnChangeAsync,
    TFormOnBlur,
    TFormOnBlurAsync,
    TFormOnSubmit,
    TFormOnSubmitAsync,
    TFormOnDynamic,
    TFormOnDynamicAsync,
    TFormOnServer,
    TParentSubmitMeta
  >,
): FieldApi<
  TParentData,
  TName,
  TData,
  TOnMount,
  TOnChange,
  TOnChangeAsync,
  TOnBlur,
  TOnBlurAsync,
  TOnSubmit,
  TOnSubmitAsync,
  TOnDynamic,
  TOnDynamicAsync,
  TFormOnMount,
  TFormOnChange,
  TFormOnChangeAsync,
  TFormOnBlur,
  TFormOnBlurAsync,
  TFormOnSubmit,
  TFormOnSubmitAsync,
  TFormOnDynamic,
  TFormOnDynamicAsync,
  TFormOnServer,
  TParentSubmitMeta
>;

Field Management

React Hooks

React-specific hooks for form and field state management with reactivity.

// Store subscription hook for reactive updates
function useStore<TState, TSelected = TState>(
  store: Store<TState>,
  selector?: (state: TState) => TSelected,
): TSelected;

// Form transformation hook
function useTransform(
  fn: (formBase: AnyFormApi) => AnyFormApi,
  deps: unknown[],
): FormTransform<any, any, any, any, any, any, any, any, any, any, any, any>;

// Field group management hook
function useFieldGroup<
  TFormData,
  TFieldGroupData,
  TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>,
  TOnMount extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnChange extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnBlur extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnSubmit extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnDynamic extends undefined | FormValidateOrFn<TFormData> = undefined,
  TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
  TComponents extends Record<string, ComponentType<any>> = {},
  TFormComponents extends Record<string, ComponentType<any>> = {},
  TSubmitMeta = never,
>(opts: FieldGroupOptions<
  TFormData,
  TFieldGroupData,
  TFields,
  TOnMount,
  TOnChange,
  TOnChangeAsync,
  TOnBlur,
  TOnBlurAsync,
  TOnSubmit,
  TOnSubmitAsync,
  TOnDynamic,
  TOnDynamicAsync,
  TOnServer,
  TSubmitMeta,
  TComponents,
  TFormComponents
>): AppFieldExtendedReactFieldGroupApi<
  TFormData,
  TFieldGroupData,
  TFields,
  TOnMount,
  TOnChange,
  TOnChangeAsync,
  TOnBlur,
  TOnBlurAsync,
  TOnSubmit,
  TOnSubmitAsync,
  TOnDynamic,
  TOnDynamicAsync,
  TOnServer,
  TSubmitMeta,
  TComponents,
  TFormComponents
>;

React Hooks

Validation System

Comprehensive validation with sync/async validators, schema integration, and error handling.

// Standard Schema validator interface
interface StandardSchemaV1<Input = unknown, Output = Input> {
  readonly '~standard': StandardSchemaV1.Props<Input, Output>;
}

namespace StandardSchemaV1 {
  interface Props<Input, Output> {
    readonly version: 1;
    readonly vendor: string;
    readonly validate: (
      value: unknown,
    ) => Result<Output> | Promise<Result<Output>>;
  }

  interface Result<Output> {
    readonly value?: Output;
    readonly issues?: ReadonlyArray<StandardSchemaV1Issue>;
  }
}

// Type guard for Standard Schema validators
function isStandardSchemaValidator(
  validator: unknown,
): validator is StandardSchemaV1;

// Standard Schema validation helpers
const standardSchemaValidators: {
  validate<TInput, TOutput>(
    value: TInput,
    schema: StandardSchemaV1<TInput, TOutput>,
  ): ValidationError | undefined;

  validateAsync<TInput, TOutput>(
    value: TInput,
    schema: StandardSchemaV1<TInput, TOutput>,
  ): Promise<ValidationError | undefined>;
};

Validation System

Advanced Form Patterns

Create custom form hooks with component injection and higher-order components.

function createFormHook<
  const TComponents extends Record<string, ComponentType<any>>,
  const TFormComponents extends Record<string, ComponentType<any>>,
>({
  fieldComponents,
  fieldContext,
  formContext,
  formComponents,
}: CreateFormHookProps<TComponents, TFormComponents>): {
  useAppForm: <TFormData, ...>(
    props: FormOptions<TFormData, ...>,
  ) => AppFieldExtendedReactFormApi<TFormData, ..., TComponents, TFormComponents>;

  withForm: <TFormData, ...>(
    props: WithFormProps<TFormData, ..., TComponents, TFormComponents>,
  ) => (props: any) => JSX.Element;

  withFieldGroup: <TFieldGroupData, TSubmitMeta, TRenderProps>(
    props: WithFieldGroupProps<TFieldGroupData, TComponents, TFormComponents, TSubmitMeta, TRenderProps>,
  ) => (props: any) => JSX.Element;
};

function createFormHookContexts(): {
  fieldContext: Context<AnyFieldApi>;
  useFieldContext: <TData>() => FieldApi<any, string, TData, ...>;
  useFormContext: () => ReactFormExtendedApi<Record<string, never>, ...>;
  formContext: Context<AnyFormApi>;
};

Advanced Form Patterns

Framework Integrations

Server-side validation utilities for Next.js, Remix, and TanStack Start.

// Next.js / Remix
function createServerValidate<
  TFormData,
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,
>(
  defaultOpts: CreateServerValidateOptions<TFormData, TOnServer>,
): (
  formData: FormData,
  info?: { resolve?: (fieldName: string) => string | File },
) => Promise<TFormData>;

const initialFormState: ServerFormState<any, undefined>;

class ServerValidateError<TFormData, TOnServer> extends Error {
  formState: ServerFormState<TFormData, TOnServer>;
}

// TanStack Start (additional)
function getFormData(): Promise<ServerFormState<any, undefined> | typeof initialFormState>;

Framework Integrations

Types

External Type References

Types from re-exported dependencies:

// From @tanstack/react-store
interface Store<TState> {
  state: TState;
  subscribe: (listener: () => void) => () => void;
  setState: (updater: (state: TState) => TState) => void;
}

// From React
type ComponentType<P = {}> = React.ComponentClass<P> | React.FunctionComponent<P>;
type PropsWithChildren<P = unknown> = P & { children?: ReactNode };
interface ReactElement {
  type: string | ComponentType<any>;
  props: any;
  key: string | number | null;
}
type ReactNode = ReactElement | string | number | boolean | null | undefined;
interface Context<T> {
  Provider: ComponentType<{ value: T }>;
  Consumer: ComponentType<{ children: (value: T) => ReactNode }>;
}

// JSX namespace for TypeScript
namespace JSX {
  type Element = ReactElement;
}

Core Type Utilities

/**
 * Deep key navigation types for accessing nested properties with type safety
 */

/**
 * Extracts all possible deep keys from a type as dot-notation strings
 * Example: For type { user: { name: string, age: number } }
 * Results in: "user" | "user.name" | "user.age"
 */
type DeepKeys<T> = unknown extends T ? string : DeepKeysAndValues<T>['key'];

/**
 * Gets the type of a value at a specific deep key path
 * Example: DeepValue<{ user: { name: string } }, "user.name"> = string
 */
type DeepValue<TValue, TAccessor> = unknown extends TValue
  ? TValue
  : TAccessor extends DeepKeys<TValue>
    ? DeepRecord<TValue>[TAccessor]
    : never;

/**
 * Filters deep keys to only those with values matching a specific type
 * Example: DeepKeysOfType<{ a: string, b: number, c: string }, string> = "a" | "c"
 */
type DeepKeysOfType<TData, TValue> = Extract<
  DeepKeysAndValues<TData>,
  AnyDeepKeyAndValue<string, TValue>
>['key'];

/**
 * Maps deep keys of TFormData to shallow keys of TFieldGroupData
 * Used for field groups to map form fields to group data structure
 * Since using template strings as keys is impractical, it relies on shallow keys only
 * Example: FieldsMap<{ user: { name: string } }, { name: string }> creates a mapping
 * from deep form paths to shallow group keys
 */
type FieldsMap<TFormData, TFieldGroupData> = {
  [K in keyof TFieldGroupData]: DeepKeysOfType<
    TFormData,
    TFieldGroupData[K] | null | undefined
  >;
};

/**
 * Updater types for functional state updates
 * Accepts either a new value or a function that receives the current value
 */
type Updater<TInput, TOutput = TInput> = TOutput | UpdaterFn<TInput, TOutput>;

/** Function type for updating values */
type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;

/**
 * Validation types
 */

/** Type representing a validation error (can be any value - string, object, etc.) */
type ValidationError = unknown;

/** Events that can trigger validation */
type ValidationCause = 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic';

/**
 * Source of validation - indicates whether a validation error originated from
 * form-level validators or field-level validators. Used in error tracking and
 * error source maps to distinguish between different validation sources.
 */
type ValidationSource = 'form' | 'field';

/**
 * Options for controlling field operations
 * Used to fine-tune behavior when updating field values or metadata
 */
interface UpdateMetaOptions {
  /** Skip metadata update (touched, dirty, etc.) */
  dontUpdateMeta?: boolean;
  /** Skip validation after update */
  dontValidate?: boolean;
  /** Skip running change/blur listeners */
  dontRunListeners?: boolean;
}

Form and Field State

interface FormState<TFormData, ...> {
  values: TFormData;
  errors: ValidationError[];
  errorMap: FormValidationErrorMap<TFormData, ...>;
  fieldMeta: Record<DeepKeys<TFormData>, FieldMeta<any, any, any, ...>>;
  canSubmit: boolean;
  isSubmitting: boolean;
  isTouched: boolean;
  isPristine: boolean;
  isDirty: boolean;
  isValid: boolean;
  isValidating: boolean;
  submissionAttempts: number;
  validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta>;
}

interface FieldState<TData> {
  value: TData;
  meta: FieldMeta<TData, any, any, ...>;
}

interface FieldMeta<TData, ...> {
  isTouched: boolean;
  isBlurred: boolean;
  isPristine: boolean;
  isDirty: boolean;
  errors: ValidationError[];
  errorMap: ValidationErrorMap;
  errorSourceMap: ValidationErrorMapSource;
  isValidating: boolean;
  isValid: boolean;
  isDefaultValue: boolean;
}