Skip to content

Commit 0932871

Browse files
ci: apply automated fixes
1 parent ec2780e commit 0932871

1 file changed

Lines changed: 68 additions & 68 deletions

File tree

src/blog/announcing-tanstack-form-v2-alpha.md

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "Form v2 is here: All you need to know about the alpha"
2+
title: 'Form v2 is here: All you need to know about the alpha'
33
published: 2026-08-06
44
excerpt: The TanStack Form v2 alpha is here with more flexible validators, schema-oriented forms, safer form composition, and simpler SSR.
55
library: form
@@ -29,12 +29,12 @@ Because v1 registered the validator once for each event, it could produce duplic
2929

3030
```ts title="v1"
3131
const form = useForm({
32-
defaultValues: { name: "" },
32+
defaultValues: { name: '' },
3333
validators: {
3434
onChange: mySchema,
3535
onBlur: mySchema,
3636
},
37-
});
37+
})
3838
```
3939

4040
#### After (v2)
@@ -43,14 +43,14 @@ In v2, you define the validator once and list both events in `triggers`. It can
4343

4444
```ts title="v2"
4545
const form = useForm({
46-
defaultValues: { name: "" },
46+
defaultValues: { name: '' },
4747
validators: [
4848
{
4949
run: mySchema,
50-
triggers: ["change", "blur"],
50+
triggers: ['change', 'blur'],
5151
},
5252
],
53-
});
53+
})
5454
```
5555

5656
### Multiple validators, one trigger
@@ -61,18 +61,18 @@ The opposite was awkward too. Say you want to run both a schema validator and a
6161

6262
```ts title="v1"
6363
const form = useForm({
64-
defaultValues: { name: "" },
64+
defaultValues: { name: '' },
6565
validators: {
6666
onChange: ({ formApi, value }) => {
67-
const errors = formApi.parseValuesWithSchema(mySchema);
67+
const errors = formApi.parseValuesWithSchema(mySchema)
6868

6969
// Stop if the schema validator found any errors.
70-
if (errors) return errors;
70+
if (errors) return errors
7171

72-
return checkReservedUsername(value);
72+
return checkReservedUsername(value)
7373
},
7474
},
75-
});
75+
})
7676
```
7777

7878
#### After (v2)
@@ -81,20 +81,20 @@ In v2, the two validators stay separate even though they share a trigger. Settin
8181

8282
```ts title="v2"
8383
const form = useForm({
84-
defaultValues: { name: "" },
84+
defaultValues: { name: '' },
8585
validators: [
8686
{
8787
run: mySchema,
88-
triggers: ["change"],
88+
triggers: ['change'],
8989
},
9090
{
9191
run: ({ value }) => checkReservedUsername(value),
92-
triggers: ["change"],
92+
triggers: ['change'],
9393
// Only run this check if the schema validator passes.
9494
bailIfInvalid: true,
9595
},
9696
],
97-
});
97+
})
9898
```
9999

100100
### Conditional validators
@@ -107,12 +107,12 @@ In v1, general conditions had to live inside the validator. The function still r
107107

108108
```ts title="v1"
109109
const form = useForm({
110-
defaultValues: { name: "" },
110+
defaultValues: { name: '' },
111111
validationLogic: revalidateLogic(),
112112
validators: {
113113
onDynamic: mySchema,
114114
},
115-
});
115+
})
116116
```
117117

118118
#### After (v2)
@@ -121,20 +121,20 @@ In v2, each trigger can include a `when` condition. The validator still runs on
121121

122122
```ts title="v2"
123123
const form = useForm({
124-
defaultValues: { name: "" },
124+
defaultValues: { name: '' },
125125
validators: [
126126
{
127127
run: schema,
128128
triggers: [
129129
{
130-
trigger: "change",
130+
trigger: 'change',
131131
// After the first submission attempt, validate every change.
132132
when: ({ formApi }) => formApi.state.submissionAttempts > 0,
133133
},
134134
],
135135
},
136136
],
137-
});
137+
})
138138
```
139139

140140
## Listeners rework
@@ -152,7 +152,7 @@ Consider an appointment form. Its schema requires a date, but we don't want to p
152152
```ts
153153
const schema = z.object({
154154
appointment: z.date(),
155-
});
155+
})
156156

157157
/*
158158
z.input<typeof schema> = {
@@ -176,10 +176,10 @@ const formOpts = formOptions({
176176
{
177177
// Error: The form is `appointment: null`, but the schema expects `Date`.
178178
run: schema,
179-
triggers: ["change"],
179+
triggers: ['change'],
180180
},
181181
],
182-
});
182+
})
183183
```
184184

185185
```ts title="Strict schema"
@@ -191,10 +191,10 @@ const formOpts = formOptions.strictSchema({
191191
validators: [
192192
{
193193
run: schema,
194-
triggers: ["change"],
194+
triggers: ['change'],
195195
},
196196
],
197-
});
197+
})
198198
```
199199

200200
```ts title="Loose schema"
@@ -206,10 +206,10 @@ const formOpts = formOptions.looseSchema({
206206
validators: [
207207
{
208208
run: schema,
209-
triggers: ["change"],
209+
triggers: ['change'],
210210
},
211211
],
212-
});
212+
})
213213
```
214214

215215
<!-- ::end:tabs -->
@@ -263,69 +263,69 @@ v1 configured server validation separately from the shared form options. Validat
263263
<!-- ::start:tabs variant="files" -->
264264

265265
```ts title="shared-code.ts"
266-
import { formOptions } from "@tanstack/react-form-nextjs";
266+
import { formOptions } from '@tanstack/react-form-nextjs'
267267

268268
export const formOpts = formOptions({
269269
defaultValues: { age: 0 },
270-
});
270+
})
271271
```
272272

273273
```ts title="action.ts"
274-
"use server";
274+
'use server'
275275

276276
import {
277277
createServerValidate,
278278
ServerValidateError,
279-
} from "@tanstack/react-form-nextjs";
280-
import { formOpts } from "./shared-code";
279+
} from '@tanstack/react-form-nextjs'
280+
import { formOpts } from './shared-code'
281281

282282
const mySchema = z.object({
283-
age: z.coerce.number().min(13, "You must be 13 at least 13"),
284-
});
283+
age: z.coerce.number().min(13, 'You must be 13 at least 13'),
284+
})
285285

286286
const serverValidate = createServerValidate({
287287
...formOpts,
288288
onServerValidate: mySchema,
289-
});
289+
})
290290

291291
export async function submit(_previous: unknown, formData: FormData) {
292292
try {
293-
const values = await serverValidate(formData);
293+
const values = await serverValidate(formData)
294294

295295
// Use values...
296296
} catch (error) {
297297
// The returned form state loses its inferred type after this check.
298298
if (error instanceof ServerValidateError) {
299-
return error.formState;
299+
return error.formState
300300
}
301301

302-
throw error;
302+
throw error
303303
}
304304
}
305305
```
306306

307307
```tsx title="client.tsx"
308-
"use client";
308+
'use client'
309309

310-
import { useActionState } from "react";
310+
import { useActionState } from 'react'
311311
import {
312312
initialFormState,
313313
mergeForm,
314314
useForm,
315315
useTransform,
316-
} from "@tanstack/react-form-nextjs";
317-
import { submit } from "./action";
318-
import { formOpts } from "./shared-code";
316+
} from '@tanstack/react-form-nextjs'
317+
import { submit } from './action'
318+
import { formOpts } from './shared-code'
319319

320320
export function Form() {
321-
const [state, action] = useActionState(submit, initialFormState);
321+
const [state, action] = useActionState(submit, initialFormState)
322322

323323
const form = useForm({
324324
...formOpts,
325325
transform: useTransform((baseForm) => mergeForm(baseForm, state!), [state]),
326-
});
326+
})
327327

328-
return <form action={action as never}>{/* form.Field components */}</form>;
328+
return <form action={action as never}>{/* form.Field components */}</form>
329329
}
330330
```
331331

@@ -338,68 +338,68 @@ v2 moves the server validator into the shared `formOpts`, so the same configurat
338338
<!-- ::start:tabs variant="files" -->
339339

340340
```ts title="shared-code.ts"
341-
import { formOptions } from "@tanstack/react-form";
341+
import { formOptions } from '@tanstack/react-form'
342342

343343
const mySchema = z.object({
344-
age: z.coerce.number().min(13, "You must be 13 at least 13"),
345-
});
344+
age: z.coerce.number().min(13, 'You must be 13 at least 13'),
345+
})
346346

347347
export const formOpts = formOptions({
348348
defaultValues: { age: 0 },
349349
validators: [
350350
{
351-
triggers: ["server"],
351+
triggers: ['server'],
352352
runOnSubmit: false,
353353
run: mySchema,
354354
},
355355
],
356-
});
356+
})
357357
```
358358

359359
```ts title="action.ts"
360-
"use server";
360+
'use server'
361361

362362
import {
363363
initialServerFormState,
364364
serverValidateHelper,
365-
} from "@tanstack/react-form";
366-
import { next } from "@tanstack/react-form-nextjs";
367-
import { formOpts } from "./shared-code";
365+
} from '@tanstack/react-form'
366+
import { next } from '@tanstack/react-form-nextjs'
367+
import { formOpts } from './shared-code'
368368

369369
const { createServerValidate } = serverValidateHelper({
370370
framework: next(),
371-
});
371+
})
372372

373-
const serverValidate = createServerValidate(formOpts);
373+
const serverValidate = createServerValidate(formOpts)
374374

375375
export async function submit(_previous: unknown, formData: FormData) {
376-
const result = await serverValidate(formData);
376+
const result = await serverValidate(formData)
377377

378378
// serverState keeps the type inferred from formOpts.
379-
if (!result.success) return result.serverState;
379+
if (!result.success) return result.serverState
380380

381381
// Use result.values...
382-
return initialServerFormState;
382+
return initialServerFormState
383383
}
384384
```
385385

386386
```tsx title="client.tsx"
387-
"use client";
387+
'use client'
388388

389-
import { useActionState } from "react";
390-
import { initialServerFormState, useForm } from "@tanstack/react-form";
391-
import { submit } from "./action";
392-
import { formOpts } from "./shared-code";
389+
import { useActionState } from 'react'
390+
import { initialServerFormState, useForm } from '@tanstack/react-form'
391+
import { submit } from './action'
392+
import { formOpts } from './shared-code'
393393

394394
export function Form() {
395-
const [serverState, action] = useActionState(submit, initialServerFormState);
395+
const [serverState, action] = useActionState(submit, initialServerFormState)
396396

397397
const form = useForm({
398398
...formOpts,
399399
serverState,
400-
});
400+
})
401401

402-
return <form action={action}>{/* form.Field components */}</form>;
402+
return <form action={action}>{/* form.Field components */}</form>
403403
}
404404
```
405405

0 commit comments

Comments
 (0)