在过去的几篇文章中,我们已经建立了一个表单来捕获一个名字、一个电子邮件地址和一个分数,并有一些合理的复杂验证规则。
在这篇文章中,我们将从一个人身上获取多个分数,并将我们的表单变成一个主-细节表单。我们将从我们在上一篇文章中实现的表单开始。
使用useFieldArray
我们将使用React Hook Form的useFieldArray 来帮助渲染和管理分数。所以,让我们导入这个:
import {
useForm,
useFieldArray} from "react-hook-form";
我们现在要捕捉一个以上的分数,所以,让我们把字段名改为scores,并把它改为数组:
type PersonScore = {
name: string;
email: string;
scores: number[];};
useFieldArray 需要使用来自 的 对象,它是表单的控制器。所以,让我们把这个结构去掉。useForm control
const {
register,
handleSubmit,
errors,
control} = useForm<PersonScore>();
我们现在可以使用useFieldArray :
const { fields, append, remove } = useFieldArray(
{
control,
name: "scores"
}
);
我们已经从useFieldArray 中解构了以下内容:
fields.这是一个数组,将帮助我们渲染每个分数字段append.这是一个函数,将允许我们添加分数字段remove.这是一个函数,将使我们能够删除分数字段。
确保至少有一个分数
我们想从一个分数字段开始。因此,让我们使用append 函数来向数组中添加一个分数:
if (fields.length === 0) {
append({});
}
该函数接收一个包含各字段默认值的对象。我们没有默认值,所以我们传递了一个空对象。
渲染分数字段
让我们继续渲染分数字段:
{
fields.map((score, index) => (
<div key={score.id}>
<div className="field">
<label htmlFor={`scores[${index}]`}>
Score{` ${index + 1}`}
</label>
<input
type="number"
id={`scores[${index}]`}
name={`scores[${index}]`}
ref={register({
required: true,
min: 0,
max: 100,
validate: isEven
})}
/>
</div>
</div>
));
}
我们正在对包含所有分数的fields 数组进行映射。我们为每个分数渲染一个label 和input 。
注意,我们使用fields 数组中的项目的id 属性作为React组件的键。这是由useFieldArray 给我们的一个指南。
我们需要给字段score[0]、score[1]、score[2]......命名,以便useFieldArray 可以管理它们。
我们的验证规则与上一篇文章中的表单的实现保持一致。让我们渲染一下验证的错误信息:
{
errors.scores &&
errors.scores[index] &&
errors.scores[index].type === "required" && (
<div className="error">
You must enter your score.
</div>
);
}
{
errors.scores &&
errors.scores[index] &&
errors.scores[index].type === "min" && (
<div className="error">
You score must be at least 0
</div>
);
}
{
errors.scores &&
errors.scores[index] &&
errors.scores[index].type === "max" && (
<div className="error">
Your score must be no more than 100
</div>
);
}
{
errors.scores &&
errors.scores[index] &&
errors.scores[index].type === "validate" && (
<div className="error">
Your score must be and even number
</div>
);
}
请注意,scores 的错误现在是在一个数组中。除此以外,每个数组的结构与普通字段相同。
添加和删除分数字段的按钮
让我们添加一个按钮来添加一个分数字段:
<button
className="add"
onClick={(e: React.MouseEvent) => {
e.preventDefault();
append({});
}}
>
Add score
</button>
当按钮被点击时,我们从useFieldArray 中调用append 函数来添加一个新的分数。
请注意,我们已经调用了事件preventDefault 方法,以确保在按钮被按下时,表单不会被提交。
我们也来添加一个按钮来删除一个分数字段:
<button
className="remove"
onClick={(e: React.MouseEvent) => {
e.preventDefault();
remove(index);
}}
>
Remove
</button>
当按钮被点击时,我们调用useFieldArray 中的函数remove ,输入要删除的分数的索引。
就这样了。这个表格的工作版本可以在CodeSandbox上找到。
总结
关于React Hook Form的系列文章已经结束了,我们用它来实现一些复杂但常见的表单需求。React Hook Form是一个很好的表单库,使用简单,性能也很好--在实现你的下一个表单时,非常值得一试!