React 表单怎么写最快:原生控制 vs React Hook Form vs Formik
·
今天我们用“报名表”这个真实案例,对比三种写法:纯 React 控制组件、React Hook Form、Formik。看完你能选出最适合自己团队的方案。
🎯 场景设定
报名表包含:
- 姓名(必填)
- 邮箱(格式校验)
- 年龄(数字范围)
- 兴趣(多选)
- 是否同意协议(勾选)
我们要做到:数据收集清晰、验证好维护、性能不卡顿。
🧱 方案一:纯 React 控制组件
function PureForm() {
const [values, setValues] = useState({
name: '',
email: '',
age: '',
hobbies: [],
agree: false,
});
const handleChange = (field) => (event) => {
const value = event.target.type === 'checkbox'
? event.target.checked
: event.target.value;
setValues((prev) => ({ ...prev, [field]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
// 自己写校验
};
return (
<form onSubmit={handleSubmit}>
<input value={values.name} onChange={handleChange('name')} />
{/* 其他字段 */}
</form>
);
}
- 优点:无需额外依赖,逻辑透明。
- 缺点:每个字段都要写
value/onChange,校验散落在各处,添加字段很麻烦。
⚙️ 方案二:React Hook Form(RHF)
import { useForm } from 'react-hook-form';
function RhfForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log('提交数据', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register('name', { required: '姓名必填' })}
placeholder="姓名"
/>
{errors.name && <p>{errors.name.message}</p>}
<input
{...register('email', {
required: '邮箱必填',
pattern: {
value: /^[\w.-]+@[\w.-]+\.[A-Za-z]{2,}$/,
message: '邮箱格式不正确',
},
})}
placeholder="邮箱"
/>
<input
type="number"
{...register('age', {
min: { value: 18, message: '年龄需 ≥ 18' },
max: { value: 60, message: '年龄需 ≤ 60' },
})}
placeholder="年龄"
/>
<label>
<input type="checkbox" {...register('agree', { required: true })} />
同意协议
</label>
<button type="submit">提交</button>
</form>
);
}
- 优点:
- 默认使用原生表单事件,性能好。
- 验证规则写在一起,结构清晰。
- 支持 Resolver(Yup/Zod)统一管理校验。
- 缺点:与 UI 库集成时需要配合
Controller。
🧰 方案三:Formik
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
const schema = Yup.object({
name: Yup.string().required('姓名必填'),
email: Yup.string().email('邮箱格式不正确').required('邮箱必填'),
age: Yup.number().min(18).max(60),
agree: Yup.boolean().isTrue('请同意协议'),
});
function FormikForm() {
return (
<Formik
initialValues={{ name: '', email: '', age: '', agree: false }}
validationSchema={schema}
onSubmit={(values) => console.log(values)}
>
{() => (
<Form>
<Field name="name" placeholder="姓名" />
<ErrorMessage name="name" component="p" />
<Field name="email" placeholder="邮箱" />
<ErrorMessage name="email" component="p" />
<Field name="age" type="number" />
<ErrorMessage name="age" component="p" />
<label>
<Field name="agree" type="checkbox" /> 同意协议
</label>
<ErrorMessage name="agree" component="p" />
<button type="submit">提交</button>
</Form>
)}
</Formik>
);
}
- 优点:
- 与 Yup 集成非常顺手。
- 表单状态(dirty/ touched)管理清晰。
- 缺点:
- 默认是受控组件,字段多时性能略逊。
- 需要配合
React.memo或FastField优化。
⚖️ 三者对比表
| 指标 | 纯 useState | React Hook Form | Formik |
|---|---|---|---|
| 开发体验 | 简单但重复代码多 | 语法简洁,api 现代 | 结构清晰,集成 Yup 强 |
| 性能 | 字段多时易卡 | 高性能(非受控) | 字段多时需优化 |
| 学习成本 | 低 | 低 | 中 |
| 社区生态 | 原生 | 活跃,社区 Hook 多 | 老牌,资料多 |
| 适用场景 | 小表单/简单需求 | 中大型表单、性能敏感 | 复杂验证、企业级项目 |
🧯 实战建议
- 简单弹窗表单 →
useState+ 自定义验证。 - 中大型表单、性能敏感 → React Hook Form。
- 复杂流程(步骤表单、动态校验) → Formik + Yup。
🚀 提升手感的小技巧
- RHF:使用
devtools插件观察表单状态。 - Formik:使用
FieldArray管理动态字段。 - 所有方案都可以配合
yup/zod写统一校验。
🏁 小练习
- 把同一个表单分别用三种方式实现,统计代码行数和提交性能。
- 用 RHF 的
Controller集成 Ant Design 的Select,记录注意事项。 - 写篇体验文:《我们团队从 Formik 迁移到 React Hook Form 的原因》。
更多推荐


所有评论(0)