如何在Formik中处理Blur事件实现自定义逻辑及表单验证
解决Formik自定义onBlur不触发验证的问题
问题根源
你直接调用handleBlur('accName')的方式不符合Formik的要求——handleBlur需要接收事件对象或规范参数,单纯传字段名无法正确标记字段的touched状态,自然触发不了验证逻辑。另外自定义逻辑的执行顺序也需要调整,要先让Formik完成内置的blur处理,再执行你的业务逻辑。
具体解决方案
1. 补充解构Formik核心方法
从useFormik中额外解构出validateField(手动触发单字段验证)和setFieldValue(安全更新表单字段值):
const { values, errors, touched, handleBlur, handleChange, handleSubmit, validateField, setFieldValue // 新增这两个方法 } = useFormik({ initialValues : customerData, validationSchema: CustomerSchema, onSubmit: async (values, action) => { // 原有提交逻辑不变 }, });
2. 重写自定义onBlur函数
让函数接收事件参数,先执行Formik的handleBlur标记字段为touched,再执行API调用、数据填充和手动验证:
const handleAcNameExists = async (event) => { // 先让Formik处理blur事件,更新touched状态 handleBlur(event); // 空值时跳过API调用,避免无效请求 if (!values.accName.trim()) return; console.log('in handleAcNameExists'); try { // 调用API获取客户数据 const customerInfo = await CustomerService.getCustomerByAccName(values.accName); // 自动填充后续输入框 if (customerInfo) { setFieldValue('address', customerInfo.address); setFieldValue('gstNo', customerInfo.gstNo); setFieldValue('mobNo', customerInfo.mobNo); // 按需填充其他字段 } // 手动触发当前字段的验证逻辑 await validateField('accName'); } catch (error) { toast.error('客户名称验证失败,请检查后重试'); // 可通过setFieldError添加自定义错误提示 // setFieldError('accName', '该客户名称不存在'); } };
3. 保持输入框的onBlur绑定
输入框的onBlur直接指向重写后的函数即可:
<input type="text" id="accName" name="accName" className="form-control" value={values.accName} onChange={handleChange} onBlur={handleAcNameExists} autoFocus />
关键说明
handleBlur(event):必须传入事件对象,Formik才能正确识别当前字段并更新touched状态,这是触发验证的前提。validateField('accName'):手动触发单字段验证,确保Yup的校验规则和自定义逻辑都能执行。setFieldValue:Formik官方提供的字段更新方法,会自动同步到values中,比直接修改customerData更符合Formik的数据流规范。
内容的提问来源于stack exchange,提问作者user3275733
相关产品推荐
相关产品推荐

