You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Zod验证与React自定义输入组件结合并传递验证逻辑?

问题描述

我创建了一个React自定义输入子组件EditText,希望将Zod验证逻辑通过props传递给该子组件以实现表单验证。目前父组件中使用register方法传递必填验证规则时,无论输入内容与否,页面始终显示“Email is required”的提示。

子组件代码

import { forwardRef } from "react";

interface EditTextProps {
    type?: string;
    leadingIcon?: React.ReactNode;
    trailingIcon?: React.ReactNode;
    placeholderText: string;
    onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
    trailingIconAction?: () => void;
    width?:string,
    name:string
}
const EditText: React.FC<EditTextProps> = forwardRef(({
    type="text",
    leadingIcon,
    trailingIcon,
    placeholderText,
    trailingIconAction,
    width,
    name
}, ref) => {
return (<input
                  ref={ref}
                    type={type}
                    name={name}
                    placeholder={placeholderText}
                    className={inputStyle}
    
                />) } 
export default EditText;

父组件代码

const Home = () {
return <EditText placeholderText={"Email"}  {...register("email", {required:true})} />
}

实际结果

无论是否输入内容,页面都会显示提示信息:Email is required


解决方案

问题根源

EditText组件没有接收并传递register方法返回的核心props(比如onChange、onBlur),导致react-hook-form无法感知输入值的变化,始终判定输入框为未填写状态。

修复步骤

  1. 扩展子组件Props类型
    让EditTextProps继承react-hook-form的UseFormRegisterReturn类型,确保能接收register返回的所有属性:

    import { forwardRef } from "react";
    import { UseFormRegisterReturn } from "react-hook-form";
    
    interface EditTextProps extends UseFormRegisterReturn {
        type?: string;
        leadingIcon?: React.ReactNode;
        trailingIcon?: React.ReactNode;
        placeholderText: string;
        trailingIconAction?: () => void;
        width?: string;
        // name已包含在UseFormRegisterReturn中,无需重复定义
    }
    
  2. 传递所有register返回的props到input元素
    在子组件中用剩余参数接收register的props,并全部传递给input:

    const EditText = forwardRef<HTMLInputElement, EditTextProps>(({
        type = "text",
        leadingIcon,
        trailingIcon,
        placeholderText,
        trailingIconAction,
        width,
        ...rest // 接收register返回的onChange、onBlur等属性
    }, ref) => {
        return (
            <div>
                {leadingIcon && <span>{leadingIcon}</span>}
                <input
                    ref={ref}
                    type={type}
                    placeholder={placeholderText}
                    className={inputStyle}
                    {...rest} // 传递所有register相关props
                />
                {trailingIcon && (
                    <span onClick={trailingIconAction}>{trailingIcon}</span>
                )}
            </div>
        );
    });
    
    export default EditText;
    
  3. 集成Zod验证(实现复杂规则)
    如果要使用Zod做schema级验证,在父组件中配置resolver:

    import { useForm } from "react-hook-form";
    import { z } from "zod";
    import { zodResolver } from "@hookform/resolvers/zod";
    
    // 定义Zod验证规则
    const emailSchema = z.object({
        email: z.string().email("请输入有效邮箱").min(1, "Email is required")
    });
    type FormValues = z.infer<typeof emailSchema>;
    
    const Home = () => {
        const { register, formState: { errors } } = useForm<FormValues>({
            resolver: zodResolver(emailSchema),
            mode: "onBlur" // 可选:设置验证触发时机,比如失去焦点时验证
        });
    
        return (
            <div>
                <EditText placeholderText={"Email"} {...register("email")} />
                {/* 显示错误提示 */}
                {errors.email && <p style={{color: "red"}}>{errors.email.message}</p>}
            </div>
        );
    };
    
  4. 调整验证触发时机(可选)
    可通过mode参数控制验证触发时机:

    const { register, formState: { errors } } = useForm<FormValues>({
        resolver: zodResolver(emailSchema),
        mode: "onChange" // 输入内容变化时触发验证
        // 或 mode: "onSubmit" 提交时验证(默认)
    });
    

关键注意事项

  • 必须传递onChange和onBlur,否则表单无法跟踪输入值变化,验证状态不会更新。
  • 不要重复定义name属性,避免覆盖register传递的name值。
  • 使用Zod需提前安装@hookform/resolvers和zod依赖。

内容的提问来源于stack exchange,提问作者Janvier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 12:22:56