
默认情况下 React Hook Form 仅在提交时触发验证,需显式设置 mode: "onChange" 才能在输入变更时实时更新 errors 对象并渲染错误提示。
默认情况下 react hook form 仅在提交时触发验证,需显式设置 `mode: "onchange"` 才能在输入变更时实时更新 errors 对象并渲染错误提示。
在使用 react-hook-form 时,表单验证行为由 useForm 的 mode 选项控制,默认值为 "onSubmit" —— 即仅在调用 handleSubmit 时才执行验证逻辑,此时 errors 对象才会被更新。因此,即使你的自定义校验函数 utils.validateFile 已正确执行并返回字符串错误消息(如 "error!"),只要尚未触发提交,errors.file?.message 始终为 undefined,导致 <p>{errors.file?.message}</p> 渲染为空。
✅ 正确做法是将 useForm 配置中的 mode 显式设为 "onChange":
const {
register,
handleSubmit,
formState: { isValid, errors },
} = useForm({
mode: "onChange", // ✅ 关键配置:启用变更时验证
defaultValues: {
compressionLevel: 90,
},
});
此外,还需注意你当前的 validateFile 函数存在两个关键问题,需同步修复:
-
文件对象访问方式错误:
<input type="file">的files是FileList,但register传入的value在未设置valueAsFile或valueAsFiles时默认为string(即文件名),而非FileList。应改用valueAsFiles: true确保获取File[]数组:
{...register("file", {
required: "文件为必填项",
valueAsFiles: true, // ✅ 启用后,value 类型为 File[]
validate: utils.validateFile,
})}
-
校验函数返回值逻辑有误:当前
validateFile使用files[0]?.type.slice(6)提取 MIME 类型后缀(如"image/png"→"png"),但部分浏览器可能返回空类型(如本地测试文件),且slice(6)对"image/jpeg"返回"jpeg"是正确的,但对"image/jpg"会失效。更健壮的方式是基于file.type或file.name.split('.').pop().toLowerCase()判断扩展名:
// validations.js
export function validateFile(files) {
if (!files || files.length === 0) return "请选择文件";
const file = files[0];
const ext = file.name.split('.').pop().toLowerCase();
const validExts = ["png", "gif", "bmp", "tiff", "webp", "jpg", "jpeg"];
return validExts.includes(ext)
? true
: `不支持的格式:.${ext},仅支持 ${validExts.join(', ')}`;
}
? 补充建议:
- 使用
required: "提示文本"替代布尔值true,使错误消息语义更清晰; - 结合
setError手动触发错误(如异步校验)时,务必确保mode匹配预期时机; - 开发阶段可启用
devMode: true获取更多调试提示。
综上,mode: "onChange" 是解决错误不显示的核心,配合 valueAsFiles: true 和健壮的校验逻辑,即可实现文件选择后即时反馈、提升用户体验。











