我正在 Vite typescript 中创建一个注册页面,其中我使用 React-hook-form 进行表单处理,并使用 Yup 进行验证。我的注册表单中有 5 个字段:用户名、全名、电子邮件、密码和头像文件输入,现在发生的情况是,我在 YUP 验证的帮助下创建了所需的所有字段,但是当我没有传递任何图像文件时它不会抛出“需要头像”的错误并跳转到无效类型的第二次验证。
这是验证模式的代码:
const validFileExtensions = ["jpg", "jpeg", "png", "gif", "svg", "webp"];
function isValidFileType(fileName?: string): boolean {
if (!fileName) return false;
const extension = fileName.split(".").pop()?.toLowerCase();
return extension ? validFileExtensions.includes(extension) : false;
}
// validation schema with yup
const validationSchema = Yup.object().shape({
email: Yup.string().required("Email is required").email("Email is invalid"),
password: Yup.string()
.required("Password is required")
.min(8, "Password must be at least 8 characters long"),
fullname: Yup.string().required("Full name is required"),
username: Yup.string()
.required("Username is required")
.min(4, "At least 4 characters ")
.matches(/^\S+$/, "No spaces allowed"),
avatar: Yup.mixed<File>()
.required("Avatar is required")
.test(
"fileType",
"Only JPG, JPEG, PNG, GIF, SVG, and WEBP files are allowed",
(value) => {
if (!value) return true;
return isValidFileType(value.name);
}
)
.test("fileSize", "File must be less than 100KB", (value) => {
if (!value) return true;
return value.size <= MAX_FILE_SIZE;
}),
// --- .test("fileType", "Unsupported file format", (value) => {
// if (!value || value.length === 0) return false;
// const file = value[0];
// return ["image/jpeg", "image/png"].includes(file.type);
// })
// .test("fileSize", "File must be less than 2MB", (value) => {
// if (!value || value.length === 0) return false;
// const file = value[0];
// return file.size <= 2 * 1024 * 1024;
// }), ---
});
使用 yupResolver 将 schema 传递到 React hook 形式的代码
const {
register,
handleSubmit,
formState: { errors },
} = useForm<SignUpFormInputs>({
resolver: yupResolver(validationSchema),
});
将错误传递到“uploadFileInput”组件的代码
<UploadFileInput
label="Upload an Avatar"
id="uploadAvatar"
name="avatar"
errors={errors.avatar?.message}
register={register}
/>
“uploadFileInput”组件的代码
import React from "react";
import { UseFormRegister } from "react-hook-form";
import { RxAvatar } from "react-icons/rx";
interface SignUpFormInputs {
email: string;
password: string;
fullname: string;
username: string;
avatar: File;
}
interface UploadFileInputProps {
id: string;
label: string;
name: keyof SignUpFormInputs;
errors?: string;
register: UseFormRegister<SignUpFormInputs>;
}
const UploadFileInput: React.FC<UploadFileInputProps> = ({
id,
label,
name,
register,
errors,
}) => {
return (
<>
<label
className="text-[17px] w-[50%] text-center text-gray-400 text-sm bg-gray-100 file:cursor-pointer p-2 cursor-pointer file:text-white"
htmlFor={id}
>
<span className=" flex items-center gap-2">
<RxAvatar size={30} />
{label}
</span>
<input id={id} type="file" className="hidden" {...register(name)} />
{errors && (
<p className="absolute ml-[-9px] text-red-500 text-sm mt-3 ">
{errors}
</p>
)}
</label>
</>
);
};
export default UploadFileInput;
问题来了
提前致谢。