为什么选择 TanStack Form?
市面上已经有了 React Hook Form 和 Formik,为什么还需要 TanStack Form?
- 极致的类型安全:从定义字段到提交数据,全程 TypeScript 推断,几乎不需要手动定义类型。
- 框架无关:虽然本文以 React 为例,但 TanStack Form 的核心逻辑可以运行在 Vue、Solid 甚至原生 JS 中。
- Headless 设计:它只负责逻辑,不负责 UI。你可以完全掌控表单的渲染方式,轻松集成 shadcn/ui 或 Material UI。
快速上手
安装依赖:
npm install @tanstack/react-form zod
这里我们配合 Zod 进行校验(可选)。
1. 定义表单
import { useForm } from '@tanstack/react-form';
function MyForm() {
const form = useForm({
defaultValues: {
firstName: '',
age: 0,
},
onSubmit: async ({ value }) => {
// value 是类型安全的
console.log(value);
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
form.handleSubmit();
}}
>
{/* 字段渲染逻辑 */}
</form>
);
}
2. 绑定字段
使用 form.Field 组件来绑定具体的输入框:
<form.Field
name="firstName"
validators={{
onChange: ({ value }) =>
!value ? '名字不能为空' : undefined,
}}
children={(field) => (
<div>
<label>First Name:</label>
<input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors ? (
<em role="alert">{field.state.meta.errors.join(', ')}</em>
) : null}
</div>
)}
/>
注意,这里使用了 Render Prop 模式。field 对象包含了当前字段的所有状态(value, errors, isTouched 等)和操作方法(handleChange, handleBlur)。
深度功能
复杂嵌套对象与数组
TanStack Form 对深层嵌套对象和数组的支持非常完美。你可以轻松处理动态增删的表单项,且不会丢失类型提示。
细粒度订阅
性能是 TanStack Form 的另一大亮点。它允许组件只订阅特定的状态变化。例如,你可以让某个组件只在 isValid 变化时重新渲染,而忽略 value 的变化。
结语
TanStack Form 或许有一定的学习曲线,但一旦上手,你会发现它处理复杂表单逻辑时的从容与优雅。对于追求长期可维护性和类型安全的大型项目,TanStack Form 是一个非常值得投入的选择。