如何使用React Hook Form实现内联(onBlur)及页面级(提交)错误展示
React Hook Form 实现分场景错误提示
这里给你实现两种错误提示的具体方案,完全匹配你的需求:内联错误在字段失焦(onBlur)时显示,页面级错误只在点击「下一步」提交时显示。
核心逻辑
利用 React Hook Form 的字段校验触发机制和状态管理:
- 内联错误:通过
trigger在字段失焦时单独校验该字段,结合errors和touched状态控制显示。 - 页面级错误:通过表单提交后的
isSubmitted状态,判断是否存在全局错误并汇总显示。
具体实现步骤
1. 初始化表单
先通过useForm初始化表单,设置默认值,同时解构需要用到的方法和状态:
import { useForm } from "react-hook-form"; function StepForm() { const { register, handleSubmit, formState: { errors, isSubmitted }, trigger } = useForm({ defaultValues: { email: "", password: "" } });
2. 实现内联级错误(onBlur触发)
给每个输入字段注册校验规则,同时在onBlur事件中调用trigger触发该字段的校验。内联错误只在字段被失焦过,或者表单已提交时显示:
<div> <label>邮箱</label> <input {...register("email", { required: "邮箱不能为空", pattern: { value: /^\S+@\S+$/i, message: "请输入有效的邮箱地址" } })} onBlur={() => trigger("email")} /> {/* 内联错误提示 */} {errors.email && (errors.email.touched || isSubmitted) && ( <span style={{ color: "red", fontSize: "12px" }}> {errors.email.message} </span> )} </div>
trigger("email"):手动触发单个字段的校验,确保失焦时就校验并显示错误。errors.email.touched:判断字段是否被失焦过,保证只有用户触碰过该字段才显示内联错误。
3. 实现页面级错误(提交时显示)
页面级错误放在表单顶部,仅在点击「下一步」提交表单后,且存在校验错误时显示:
{isSubmitted && Object.keys(errors).length > 0 && ( <div style={{ color: "red", marginBottom: "16px" }}> 请修正以下错误:{Object.values(errors).map(err => err.message).join("、")} </div> )}
isSubmitted:标记表单是否被提交过,确保只有提交后才显示全局错误汇总。
4. 提交逻辑
通过handleSubmit包裹提交函数,只有当所有字段校验通过时,才会执行后续的下一步逻辑:
const onSubmit = (data) => { // 这里写校验通过后的下一步逻辑,比如页面跳转、数据提交等 alert("校验通过,进入下一步"); }; // 表单绑定提交事件 <form onSubmit={handleSubmit(onSubmit)}> {/* 表单内容 */} <button type="submit">下一步</button> </form>
完整示例代码
import { useForm } from "react-hook-form"; function StepForm() { const { register, handleSubmit, formState: { errors, isSubmitted }, trigger } = useForm({ defaultValues: { email: "", password: "" } }); const onSubmit = (data) => { alert("表单校验通过,进入下一步"); }; return ( <form onSubmit={handleSubmit(onSubmit)} style={{ padding: "20px" }}> {/* 页面级错误提示 */} {isSubmitted && Object.keys(errors).length > 0 && ( <div style={{ color: "red", marginBottom: "16px" }}> 请修正以下错误:{Object.values(errors).map(err => err.message).join("、")} </div> )} <div style={{ marginBottom: "16px" }}> <label style={{ display: "inline-block", width: "80px" }}>邮箱</label> <input {...register("email", { required: "邮箱不能为空", pattern: { value: /^\S+@\S+$/i, message: "请输入有效的邮箱地址" } })} onBlur={() => trigger("email")} style={{ padding: "4px" }} /> {errors.email && (errors.email.touched || isSubmitted) && ( <div style={{ color: "red", fontSize: "12px", marginTop: "4px" }}> {errors.email.message} </div> )} </div> <div style={{ marginBottom: "16px" }}> <label style={{ display: "inline-block", width: "80px" }}>密码</label> <input type="password" {...register("password", { required: "密码不能为空", minLength: { value: 6, message: "密码长度不能少于6位" } })} onBlur={() => trigger("password")} style={{ padding: "4px" }} /> {errors.password && (errors.password.touched || isSubmitted) && ( <div style={{ color: "red", fontSize: "12px", marginTop: "4px" }}> {errors.password.message} </div> )} </div> <button type="submit" style={{ padding: "6px 16px" }}>下一步</button> </form> ); } export default StepForm;
关键细节说明
- 内联错误的显示条件:确保用户触碰过字段(失焦)或表单已提交,避免页面刚加载就显示错误。
- 页面级错误仅在提交后显示:通过
isSubmitted状态控制,不会提前干扰用户输入。 - 单个字段校验:用
trigger精准触发对应字段的校验,避免全局校验提前触发。
内容的提问来源于stack exchange,提问作者Tanu Agrawal
相关产品推荐
相关产品推荐

