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

React表单能否为不同字段配置onBlur与onSubmit验证模式?

实现按需触发的表单验证(仅提交时显示密码不匹配错误)

完全可以实现,按照下面的步骤修改代码就行:

  1. 保持表单的mode: 'onTouched',确保普通字段(邮箱、姓名等)在失焦时触发验证,错误实时显示,提交按钮的禁用状态跟着isValid走。
  2. 删掉你手动用watch判断密码匹配的逻辑,改用React Hook Form自带的错误提示,只有在用户点击提交后才显示密码不匹配的错误。
  3. 调整Yup Schema的验证逻辑,确保密码匹配的校验在提交时触发。

修改后的完整代码

Yup Schema 部分

const schema = Yup.object().shape({
    email: Yup.string()
        .required('emailRequired')
        .email('invalidEmail'),
    firstname: Yup.string().required('firstnameRequired'),
    lastname: Yup.string().required('lastnameRequired'),
    password: Yup.string()
        .required('passwordRequired')
        .min(PASSWORD_MIN, 'minlengthPassword')
        .max(PASSWORD_MAX, 'maxlengthPassword'),
    confirmedPassword: Yup.string()
        .required('confirmedPasswordRequired') // 先校验必填,再做密码匹配
        .test('password-match', 'passwordNoMatch', function(value) {
            // 通过上下文获取密码字段值,做匹配校验
            return this.parent.password === value;
        })
});

表单组件部分

const App = () => {
     const {
        control,
        handleSubmit,
        formState: {errors, isValid}
    } = useForm({
        resolver: yupResolver(schema),
        mode: 'onTouched',
        defaultValues: {
            firstname: "",
            lastname: "",
            email: "",
            password: "",
            confirmedPassword: "",
            lang: i18n.language
        }
    });

    // 提交逻辑
    const onSubmit = (data) => {
        // 这里写你的提交代码,比如调用后端接口
        console.log('提交的表单数据:', data);
    };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
        {/* 姓名字段示例 */}
        <Controller
            control={control}
            name="firstname"
            render={({field: {onChange, value}}) => (
                <FormInput
                    name="firstname"
                    onChange={onChange}
                    value={value}
                    errors={errors}
                    clearErrors={clearErrors}
                />
            )}
        />
        {errors.firstname && <Text>{t(errors.firstname.message, {ns: 'errors'})}</Text>}

        {/* 邮箱字段 */}
        <Controller
            control={control}
            name="email"
            render={({field: {onChange, value}}) => (
                <FormInput
                    name="email"
                    secureTextEntry={false}
                    onChange={onChange}
                    value={value}
                    errors={errors}
                    clearErrors={clearErrors}
                />
            )}
        />
        {errors.email && <Text>{t(errors.email.message, {ns: 'errors'})}</Text>}

        {/* 密码字段 */}
        <Controller
            control={control}
            name="password"
            render={({field: {onChange, value}}) => (
                <FormInput
                    name="password"
                    secureTextEntry={true}
                    onChange={onChange}
                    value={value}
                    errors={errors}
                    clearErrors={clearErrors}
                />
            )}
        />
        {errors.password && <Text>{t(errors.password.message, {ns: 'errors'})}</Text>}

        {/* 确认密码字段 */}
        <Controller
            control={control}
            name="confirmedPassword"
            render={({field: {onChange, value}}) => (
                <FormInput
                    name="confirmedPassword"
                    secureTextEntry={true}
                    onChange={onChange}
                    value={value}
                    errors={errors}
                    clearErrors={clearErrors}
                />
            )}
        />
        {/* 只有提交后验证失败,才显示密码不匹配错误 */}
        {errors.confirmedPassword && <Text style={styles.pwdNoMatch}>{t(errors.confirmedPassword.message, {ns: 'errors'})}</Text>}

        {/* 提交按钮:isValid为true时才启用 */}
        <Button 
            type="submit" 
            disabled={!isValid}
        >
            {t('submit')}
        </Button>
    </form>
  )
}

核心逻辑说明

  • 普通字段验证:因为设置了mode: 'onTouched',用户离开字段(blur)时就会触发验证,错误实时显示,isValid会自动更新,确保提交按钮在有错误时保持禁用。
  • 密码匹配验证:handleSubmit在用户点击提交时,会强制触发所有字段的完整验证,包括confirmedPassword的匹配校验。此时如果密码不匹配,errors.confirmedPassword会被赋值,对应的错误提示才会显示。
  • 避免实时错误:不再用watch实时监听密码输入,彻底解决了输入时就显示密码不匹配错误的问题,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:45:37