React表单能否为不同字段配置onBlur与onSubmit验证模式?
实现按需触发的表单验证(仅提交时显示密码不匹配错误)
完全可以实现,按照下面的步骤修改代码就行:
- 保持表单的
mode: 'onTouched',确保普通字段(邮箱、姓名等)在失焦时触发验证,错误实时显示,提交按钮的禁用状态跟着isValid走。 - 删掉你手动用
watch判断密码匹配的逻辑,改用React Hook Form自带的错误提示,只有在用户点击提交后才显示密码不匹配的错误。 - 调整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
相关产品推荐
相关产品推荐

