TanStack Form 与您以前使用过的大多数表单库不同。它专为大规模生产环境而设计,注重类型安全、性能和组合,以提供无与伦比的开发体验。
因此,我们围绕库的使用制定了一套理念,该理念重视可伸缩性和长期开发体验,而不是简短且易于共享的代码片段。
以下是一个遵循我们许多最佳实践的表单示例,它将使您在短暂的入门体验后能够快速开发甚至高复杂度的表单:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { createFormHook, createFormHookContexts } from '@tanstack/react-form'
// 表单组件,用于从表单钩子预绑定事件;有关更多信息,请查看我们的“表单组合”指南
import { TextField, NumberField, SubmitButton } from '~our-app/ui-library'
// 我们还支持 Valibot、ArkType 和任何其他标准模式库
import { z } from 'zod'
const { fieldContext, formContext } = createFormHookContexts()
// 允许我们将组件绑定到表单以保持类型安全,但减少生产样板代码
// 定义一次即可在整个应用程序中生成一致的表单实例
const { useAppForm } = createFormHook({
fieldComponents: {
TextField,
NumberField,
},
formComponents: {
SubmitButton,
},
fieldContext,
formContext,
})
const PeoplePage = () => {
const form = useAppForm({
defaultValues: {
username: '',
age: 0,
},
validators: {
// 传递模式或函数进行校验
onChange: z.object({
username: z.string(),
age: z.number().min(13),
}),
},
onSubmit: ({ value }) => {
// 处理表单数据
alert(JSON.stringify(value, null, 2))
},
})
return (
<form
onSubmit={(e) => {
e.preventDefault()
form.handleSubmit()
}}
>
<h1>个人信息</h1>
{/* 组件绑定到 `form` 和 `field` 以确保极高的类型安全性 */}
{/* 使用 `form.AppField` 渲染绑定到单个字段的组件 */}
<form.AppField
name="username"
children={(field) => <field.TextField label="全名" />}
/>
{/* 如果拼写错误,“name”属性将引发 TypeScript 错误 */}
<form.AppField
name="age"
children={(field) => <field.NumberField label="年龄" />}
/>
{/* `form.AppForm` 中的组件可以访问表单上下文 */}
<form.AppForm>
<form.SubmitButton />
</form.AppForm>
</form>
)
}
const rootElement = document.getElementById('root')!
ReactDOM.createRoot(rootElement).render(<PeoplePage />)
import React from 'react'
import ReactDOM from 'react-dom/client'
import { createFormHook, createFormHookContexts } from '@tanstack/react-form'
// 表单组件,用于从表单钩子预绑定事件;有关更多信息,请查看我们的“表单组合”指南
import { TextField, NumberField, SubmitButton } from '~our-app/ui-library'
// 我们还支持 Valibot、ArkType 和任何其他标准模式库
import { z } from 'zod'
const { fieldContext, formContext } = createFormHookContexts()
// 允许我们将组件绑定到表单以保持类型安全,但减少生产样板代码
// 定义一次即可在整个应用程序中生成一致的表单实例
const { useAppForm } = createFormHook({
fieldComponents: {
TextField,
NumberField,
},
formComponents: {
SubmitButton,
},
fieldContext,
formContext,
})
const PeoplePage = () => {
const form = useAppForm({
defaultValues: {
username: '',
age: 0,
},
validators: {
// 传递模式或函数进行校验
onChange: z.object({
username: z.string(),
age: z.number().min(13),
}),
},
onSubmit: ({ value }) => {
// 处理表单数据
alert(JSON.stringify(value, null, 2))
},
})
return (
<form
onSubmit={(e) => {
e.preventDefault()
form.handleSubmit()
}}
>
<h1>个人信息</h1>
{/* 组件绑定到 `form` 和 `field` 以确保极高的类型安全性 */}
{/* 使用 `form.AppField` 渲染绑定到单个字段的组件 */}
<form.AppField
name="username"
children={(field) => <field.TextField label="全名" />}
/>
{/* 如果拼写错误,“name”属性将引发 TypeScript 错误 */}
<form.AppField
name="age"
children={(field) => <field.NumberField label="年龄" />}
/>
{/* `form.AppForm` 中的组件可以访问表单上下文 */}
<form.AppForm>
<form.SubmitButton />
</form.AppForm>
</form>
)
}
const rootElement = document.getElementById('root')!
ReactDOM.createRoot(rootElement).render(<PeoplePage />)
虽然我们通常建议使用 createFormHook 来减少长期的样板代码,但我们也支持使用 useForm 和 form.Field 的一次性组件和其他行为:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { useForm } from '@tanstack/react-form'
const PeoplePage = () => {
const form = useForm({
defaultValues: {
username: '',
age: 0,
},
onSubmit: ({ value }) => {
// 处理表单数据
alert(JSON.stringify(value, null, 2))
},
})
return (
<form.Field
name="age"
validators={{
// 我们可以选择表单范围或字段特定的校验器
onChange: ({ value }) =>
value > 13 ? undefined : '必须年满 13 岁',
}}
children={(field) => (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) => field.handleChange(e.target.valueAsNumber)}
/>
{!field.state.meta.isValid && (
<em>{field.state.meta.errors.join(',')}</em>
)}
</>
)}
/>
)
}
const rootElement = document.getElementById('root')!
ReactDOM.createRoot(rootElement).render(<PeoplePage />)
import React from 'react'
import ReactDOM from 'react-dom/client'
import { useForm } from '@tanstack/react-form'
const PeoplePage = () => {
const form = useForm({
defaultValues: {
username: '',
age: 0,
},
onSubmit: ({ value }) => {
// 处理表单数据
alert(JSON.stringify(value, null, 2))
},
})
return (
<form.Field
name="age"
validators={{
// 我们可以选择表单范围或字段特定的校验器
onChange: ({ value }) =>
value > 13 ? undefined : '必须年满 13 岁',
}}
children={(field) => (
<>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) => field.handleChange(e.target.valueAsNumber)}
/>
{!field.state.meta.isValid && (
<em>{field.state.meta.errors.join(',')}</em>
)}
</>
)}
/>
)
}
const rootElement = document.getElementById('root')!
ReactDOM.createRoot(rootElement).render(<PeoplePage />)