or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

index.mddocs/

0

# TanStack React Form

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: @tanstack/react-form

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Version**: 1.23.7

10

- **Installation**: `npm install @tanstack/react-form`

11

12

## Core Imports

13

14

```typescript

15

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

16

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

17

```

18

19

For CommonJS:

20

21

```javascript

22

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

23

```

24

25

Framework-specific imports:

26

27

```typescript

28

// Next.js

29

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

30

31

// Remix

32

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

33

34

// TanStack Start

35

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

36

```

37

38

## Basic Usage

39

40

```typescript

41

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

42

43

function MyForm() {

44

const form = useForm({

45

defaultValues: {

46

firstName: '',

47

lastName: '',

48

email: '',

49

},

50

onSubmit: async ({ value }) => {

51

console.log('Form submitted:', value);

52

},

53

});

54

55

return (

56

<form

57

onSubmit={(e) => {

58

e.preventDefault();

59

form.handleSubmit();

60

}}

61

>

62

<form.Field

63

name="firstName"

64

validators={{

65

onChange: ({ value }) =>

66

value.length < 2 ? 'First name must be at least 2 characters' : undefined,

67

}}

68

>

69

{(field) => (

70

<div>

71

<label htmlFor={field.name}>First Name:</label>

72

<input

73

id={field.name}

74

value={field.state.value}

75

onChange={(e) => field.handleChange(e.target.value)}

76

onBlur={field.handleBlur}

77

/>

78

{field.state.meta.errors.length > 0 && (

79

<em>{field.state.meta.errors[0]}</em>

80

)}

81

</div>

82

)}

83

</form.Field>

84

85

<button type="submit" disabled={!form.state.canSubmit}>

86

Submit

87

</button>

88

</form>

89

);

90

}

91

```

92

93

## Architecture

94

95

TanStack React Form is built on several core concepts:

96

97

- **FormApi**: Core form state manager handling validation, submission, and field coordination

98

- **FieldApi**: Individual field state manager with validation and metadata tracking

99

- **FieldGroupApi**: Manages related fields as a logical unit with shared state

100

- **Store Pattern**: Reactive state management using `@tanstack/react-store` for efficient re-renders

101

- **Validation System**: Supports synchronous/asynchronous validators at form and field levels

102

- **Schema Integration**: Compatible with validation libraries via Standard Schema interface

103

- **Framework Adapters**: Server-side validation for Next.js, Remix, and TanStack Start

104

105

## Capabilities

106

107

### Form Management

108

109

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

110

111

```typescript { .api }

112

function useForm<

113

TFormData,

114

TOnMount extends undefined | FormValidateOrFn<TFormData> = undefined,

115

TOnChange extends undefined | FormValidateOrFn<TFormData> = undefined,

116

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

117

TOnBlur extends undefined | FormValidateOrFn<TFormData> = undefined,

118

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

119

TOnSubmit extends undefined | FormValidateOrFn<TFormData> = undefined,

120

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

121

TOnDynamic extends undefined | FormValidateOrFn<TFormData> = undefined,

122

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

123

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

124

TSubmitMeta = never,

125

>(

126

opts?: FormOptions<

127

TFormData,

128

TOnMount,

129

TOnChange,

130

TOnChangeAsync,

131

TOnBlur,

132

TOnBlurAsync,

133

TOnSubmit,

134

TOnSubmitAsync,

135

TOnDynamic,

136

TOnDynamicAsync,

137

TOnServer,

138

TSubmitMeta

139

>,

140

): ReactFormExtendedApi<

141

TFormData,

142

TOnMount,

143

TOnChange,

144

TOnChangeAsync,

145

TOnBlur,

146

TOnBlurAsync,

147

TOnSubmit,

148

TOnSubmitAsync,

149

TOnDynamic,

150

TOnDynamicAsync,

151

TOnServer,

152

TSubmitMeta

153

>;

154

```

155

156

[Form Management](./form-api.md)

157

158

### Field Management

159

160

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

161

162

```typescript { .api }

163

function useField<

164

TParentData,

165

TName extends DeepKeys<TParentData>,

166

TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,

167

TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,

168

TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,

169

TOnChangeAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,

170

TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,

171

TOnBlurAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,

172

TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,

173

TOnSubmitAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,

174

TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData> = undefined,

175

TOnDynamicAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData> = undefined,

176

TFormOnMount extends undefined | FormValidateOrFn<TParentData> = undefined,

177

TFormOnChange extends undefined | FormValidateOrFn<TParentData> = undefined,

178

TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,

179

TFormOnBlur extends undefined | FormValidateOrFn<TParentData> = undefined,

180

TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,

181

TFormOnSubmit extends undefined | FormValidateOrFn<TParentData> = undefined,

182

TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,

183

TFormOnDynamic extends undefined | FormValidateOrFn<TParentData> = undefined,

184

TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,

185

TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData> = undefined,

186

TParentSubmitMeta = never,

187

>(

188

opts: UseFieldOptions<

189

TParentData,

190

TName,

191

TData,

192

TOnMount,

193

TOnChange,

194

TOnChangeAsync,

195

TOnBlur,

196

TOnBlurAsync,

197

TOnSubmit,

198

TOnSubmitAsync,

199

TOnDynamic,

200

TOnDynamicAsync,

201

TFormOnMount,

202

TFormOnChange,

203

TFormOnChangeAsync,

204

TFormOnBlur,

205

TFormOnBlurAsync,

206

TFormOnSubmit,

207

TFormOnSubmitAsync,

208

TFormOnDynamic,

209

TFormOnDynamicAsync,

210

TFormOnServer,

211

TParentSubmitMeta

212

>,

213

): FieldApi<

214

TParentData,

215

TName,

216

TData,

217

TOnMount,

218

TOnChange,

219

TOnChangeAsync,

220

TOnBlur,

221

TOnBlurAsync,

222

TOnSubmit,

223

TOnSubmitAsync,

224

TOnDynamic,

225

TOnDynamicAsync,

226

TFormOnMount,

227

TFormOnChange,

228

TFormOnChangeAsync,

229

TFormOnBlur,

230

TFormOnBlurAsync,

231

TFormOnSubmit,

232

TFormOnSubmitAsync,

233

TFormOnDynamic,

234

TFormOnDynamicAsync,

235

TFormOnServer,

236

TParentSubmitMeta

237

>;

238

```

239

240

[Field Management](./field-api.md)

241

242

### React Hooks

243

244

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

245

246

```typescript { .api }

247

// Store subscription hook for reactive updates

248

function useStore<TState, TSelected = TState>(

249

store: Store<TState>,

250

selector?: (state: TState) => TSelected,

251

): TSelected;

252

253

// Form transformation hook

254

function useTransform(

255

fn: (formBase: AnyFormApi) => AnyFormApi,

256

deps: unknown[],

257

): FormTransform<any, any, any, any, any, any, any, any, any, any, any, any>;

258

259

// Field group management hook

260

function useFieldGroup<

261

TFormData,

262

TFieldGroupData,

263

TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>,

264

TOnMount extends undefined | FormValidateOrFn<TFormData> = undefined,

265

TOnChange extends undefined | FormValidateOrFn<TFormData> = undefined,

266

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

267

TOnBlur extends undefined | FormValidateOrFn<TFormData> = undefined,

268

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

269

TOnSubmit extends undefined | FormValidateOrFn<TFormData> = undefined,

270

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

271

TOnDynamic extends undefined | FormValidateOrFn<TFormData> = undefined,

272

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

273

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

274

TComponents extends Record<string, ComponentType<any>> = {},

275

TFormComponents extends Record<string, ComponentType<any>> = {},

276

TSubmitMeta = never,

277

>(opts: FieldGroupOptions<

278

TFormData,

279

TFieldGroupData,

280

TFields,

281

TOnMount,

282

TOnChange,

283

TOnChangeAsync,

284

TOnBlur,

285

TOnBlurAsync,

286

TOnSubmit,

287

TOnSubmitAsync,

288

TOnDynamic,

289

TOnDynamicAsync,

290

TOnServer,

291

TSubmitMeta,

292

TComponents,

293

TFormComponents

294

>): AppFieldExtendedReactFieldGroupApi<

295

TFormData,

296

TFieldGroupData,

297

TFields,

298

TOnMount,

299

TOnChange,

300

TOnChangeAsync,

301

TOnBlur,

302

TOnBlurAsync,

303

TOnSubmit,

304

TOnSubmitAsync,

305

TOnDynamic,

306

TOnDynamicAsync,

307

TOnServer,

308

TSubmitMeta,

309

TComponents,

310

TFormComponents

311

>;

312

```

313

314

[React Hooks](./hooks.md)

315

316

### Validation System

317

318

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

319

320

```typescript { .api }

321

// Standard Schema validator interface

322

interface StandardSchemaV1<Input = unknown, Output = Input> {

323

readonly '~standard': StandardSchemaV1.Props<Input, Output>;

324

}

325

326

namespace StandardSchemaV1 {

327

interface Props<Input, Output> {

328

readonly version: 1;

329

readonly vendor: string;

330

readonly validate: (

331

value: unknown,

332

) => Result<Output> | Promise<Result<Output>>;

333

}

334

335

interface Result<Output> {

336

readonly value?: Output;

337

readonly issues?: ReadonlyArray<StandardSchemaV1Issue>;

338

}

339

}

340

341

// Type guard for Standard Schema validators

342

function isStandardSchemaValidator(

343

validator: unknown,

344

): validator is StandardSchemaV1;

345

346

// Standard Schema validation helpers

347

const standardSchemaValidators: {

348

validate<TInput, TOutput>(

349

value: TInput,

350

schema: StandardSchemaV1<TInput, TOutput>,

351

): ValidationError | undefined;

352

353

validateAsync<TInput, TOutput>(

354

value: TInput,

355

schema: StandardSchemaV1<TInput, TOutput>,

356

): Promise<ValidationError | undefined>;

357

};

358

```

359

360

[Validation System](./validation.md)

361

362

### Advanced Form Patterns

363

364

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

365

366

```typescript { .api }

367

function createFormHook<

368

const TComponents extends Record<string, ComponentType<any>>,

369

const TFormComponents extends Record<string, ComponentType<any>>,

370

>({

371

fieldComponents,

372

fieldContext,

373

formContext,

374

formComponents,

375

}: CreateFormHookProps<TComponents, TFormComponents>): {

376

useAppForm: <TFormData, ...>(

377

props: FormOptions<TFormData, ...>,

378

) => AppFieldExtendedReactFormApi<TFormData, ..., TComponents, TFormComponents>;

379

380

withForm: <TFormData, ...>(

381

props: WithFormProps<TFormData, ..., TComponents, TFormComponents>,

382

) => (props: any) => JSX.Element;

383

384

withFieldGroup: <TFieldGroupData, TSubmitMeta, TRenderProps>(

385

props: WithFieldGroupProps<TFieldGroupData, TComponents, TFormComponents, TSubmitMeta, TRenderProps>,

386

) => (props: any) => JSX.Element;

387

};

388

389

function createFormHookContexts(): {

390

fieldContext: Context<AnyFieldApi>;

391

useFieldContext: <TData>() => FieldApi<any, string, TData, ...>;

392

useFormContext: () => ReactFormExtendedApi<Record<string, never>, ...>;

393

formContext: Context<AnyFormApi>;

394

};

395

```

396

397

[Advanced Form Patterns](./advanced.md)

398

399

### Framework Integrations

400

401

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

402

403

```typescript { .api }

404

// Next.js / Remix

405

function createServerValidate<

406

TFormData,

407

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

408

>(

409

defaultOpts: CreateServerValidateOptions<TFormData, TOnServer>,

410

): (

411

formData: FormData,

412

info?: { resolve?: (fieldName: string) => string | File },

413

) => Promise<TFormData>;

414

415

const initialFormState: ServerFormState<any, undefined>;

416

417

class ServerValidateError<TFormData, TOnServer> extends Error {

418

formState: ServerFormState<TFormData, TOnServer>;

419

}

420

421

// TanStack Start (additional)

422

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

423

```

424

425

[Framework Integrations](./framework-integrations.md)

426

427

## Types

428

429

### External Type References

430

431

Types from re-exported dependencies:

432

433

```typescript { .api }

434

// From @tanstack/react-store

435

interface Store<TState> {

436

state: TState;

437

subscribe: (listener: () => void) => () => void;

438

setState: (updater: (state: TState) => TState) => void;

439

}

440

441

// From React

442

type ComponentType<P = {}> = React.ComponentClass<P> | React.FunctionComponent<P>;

443

type PropsWithChildren<P = unknown> = P & { children?: ReactNode };

444

interface ReactElement {

445

type: string | ComponentType<any>;

446

props: any;

447

key: string | number | null;

448

}

449

type ReactNode = ReactElement | string | number | boolean | null | undefined;

450

interface Context<T> {

451

Provider: ComponentType<{ value: T }>;

452

Consumer: ComponentType<{ children: (value: T) => ReactNode }>;

453

}

454

455

// JSX namespace for TypeScript

456

namespace JSX {

457

type Element = ReactElement;

458

}

459

```

460

461

### Core Type Utilities

462

463

```typescript { .api }

464

/**

465

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

466

*/

467

468

/**

469

* Extracts all possible deep keys from a type as dot-notation strings

470

* Example: For type { user: { name: string, age: number } }

471

* Results in: "user" | "user.name" | "user.age"

472

*/

473

type DeepKeys<T> = unknown extends T ? string : DeepKeysAndValues<T>['key'];

474

475

/**

476

* Gets the type of a value at a specific deep key path

477

* Example: DeepValue<{ user: { name: string } }, "user.name"> = string

478

*/

479

type DeepValue<TValue, TAccessor> = unknown extends TValue

480

? TValue

481

: TAccessor extends DeepKeys<TValue>

482

? DeepRecord<TValue>[TAccessor]

483

: never;

484

485

/**

486

* Filters deep keys to only those with values matching a specific type

487

* Example: DeepKeysOfType<{ a: string, b: number, c: string }, string> = "a" | "c"

488

*/

489

type DeepKeysOfType<TData, TValue> = Extract<

490

DeepKeysAndValues<TData>,

491

AnyDeepKeyAndValue<string, TValue>

492

>['key'];

493

494

/**

495

* Maps deep keys of TFormData to shallow keys of TFieldGroupData

496

* Used for field groups to map form fields to group data structure

497

* Since using template strings as keys is impractical, it relies on shallow keys only

498

* Example: FieldsMap<{ user: { name: string } }, { name: string }> creates a mapping

499

* from deep form paths to shallow group keys

500

*/

501

type FieldsMap<TFormData, TFieldGroupData> = {

502

[K in keyof TFieldGroupData]: DeepKeysOfType<

503

TFormData,

504

TFieldGroupData[K] | null | undefined

505

>;

506

};

507

508

/**

509

* Updater types for functional state updates

510

* Accepts either a new value or a function that receives the current value

511

*/

512

type Updater<TInput, TOutput = TInput> = TOutput | UpdaterFn<TInput, TOutput>;

513

514

/** Function type for updating values */

515

type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;

516

517

/**

518

* Validation types

519

*/

520

521

/** Type representing a validation error (can be any value - string, object, etc.) */

522

type ValidationError = unknown;

523

524

/** Events that can trigger validation */

525

type ValidationCause = 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic';

526

527

/**

528

* Source of validation - indicates whether a validation error originated from

529

* form-level validators or field-level validators. Used in error tracking and

530

* error source maps to distinguish between different validation sources.

531

*/

532

type ValidationSource = 'form' | 'field';

533

534

/**

535

* Options for controlling field operations

536

* Used to fine-tune behavior when updating field values or metadata

537

*/

538

interface UpdateMetaOptions {

539

/** Skip metadata update (touched, dirty, etc.) */

540

dontUpdateMeta?: boolean;

541

/** Skip validation after update */

542

dontValidate?: boolean;

543

/** Skip running change/blur listeners */

544

dontRunListeners?: boolean;

545

}

546

```

547

548

### Form and Field State

549

550

```typescript { .api }

551

interface FormState<TFormData, ...> {

552

values: TFormData;

553

errors: ValidationError[];

554

errorMap: FormValidationErrorMap<TFormData, ...>;

555

fieldMeta: Record<DeepKeys<TFormData>, FieldMeta<any, any, any, ...>>;

556

canSubmit: boolean;

557

isSubmitting: boolean;

558

isTouched: boolean;

559

isPristine: boolean;

560

isDirty: boolean;

561

isValid: boolean;

562

isValidating: boolean;

563

submissionAttempts: number;

564

validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta>;

565

}

566

567

interface FieldState<TData> {

568

value: TData;

569

meta: FieldMeta<TData, any, any, ...>;

570

}

571

572

interface FieldMeta<TData, ...> {

573

isTouched: boolean;

574

isBlurred: boolean;

575

isPristine: boolean;

576

isDirty: boolean;

577

errors: ValidationError[];

578

errorMap: ValidationErrorMap;

579

errorSourceMap: ValidationErrorMapSource;

580

isValidating: boolean;

581

isValid: boolean;

582

isDefaultValue: boolean;

583

}

584

```

585