无输入框时Formik onSubmit失效求助(Next.js+TS+Yup)
解决Formik无输入框时handleSubmit不触发的问题
问题根源
- 输入框隐藏时,Yup验证规则仍强制要求
name字段必填,Formik验证失败,导致onSubmit无法触发。 - 无表单交互控件时,部分浏览器会拦截表单的默认提交行为。
解决方案
方案1:动态调整验证规则
根据输入框是否显示,动态修改Yup的验证规则,隐藏输入框时移除name的必填限制:
export const Form = () => { const username = false; // 动态生成验证规则 const validationSchema: SchemaOf<FormValues> = object({ name: username ? string().min(1).max(30, "maxLengthError").required("requiredError") : string().nullable(), // 隐藏时允许字段为空 }); const handleAlternative = (values) => console.log("Alternative", values); const formik = useFormik({ initialValues, validationSchema, onSubmit: (values, { resetForm }) => { console.log(values); handleAlternative(values); resetForm(); }, }); return ( <form onSubmit={formik.handleSubmit} className={styles.form}> {username && ( <Input id="name" type="name" label="Name" value={formik.values.name} error={!!formik.errors.name} errorMessage={formik.errors.name} onChange={formik.handleChange} /> )} <div className="justify-center gap-4"> <Button type="submit" // 隐藏输入框时按钮无需禁用 disabled={username && (!formik.isValid || !formik.dirty)} > Submit </Button> </div> </form> ); };
方案2:直接调用Formik的submitForm方法
绕过表单默认提交逻辑,在按钮点击时手动触发验证并提交:
export const Form = () => { const username = false; const validationSchema: SchemaOf<FormValues> = object({ name: string().min(1).max(30, "maxLengthError").required("requiredError"), }); const handleAlternative = (values) => console.log("Alternative", values); const formik = useFormik({ initialValues, validationSchema, onSubmit: (values, { resetForm }) => { console.log(values); handleAlternative(values); resetForm(); }, }); return ( <form className={styles.form}> {/* 移除form上的onSubmit绑定 */} {username && ( <Input id="name" type="name" label="Name" value={formik.values.name} error={!!formik.errors.name} errorMessage={formik.errors.name} onChange={formik.handleChange} /> )} <div className="justify-center gap-4"> <Button onClick={async () => { // 手动触发验证 await formik.validateForm(); // 验证通过则执行提交 if (formik.isValid) { formik.submitForm(); } }} disabled={username && (!formik.isValid || !formik.dirty)} > Submit </Button> </div> </form> ); };
方案3:添加隐藏表单控件(兼容旧浏览器)
针对部分拦截无控件表单提交的浏览器,添加隐藏输入框确保表单存在可提交控件:
export const Form = () => { const username = false; // ... 其他代码不变 return ( <form onSubmit={formik.handleSubmit} className={styles.form}> {username && ( <Input id="name" type="name" label="Name" value={formik.values.name} error={!!formik.errors.name} errorMessage={formik.errors.name} onChange={formik.handleChange} /> )} {/* 隐藏输入框,仅在无显示输入时渲染 */} {!username && ( <input type="hidden" id="name" name="name" value={formik.values.name} onChange={formik.handleChange} /> )} <div className="justify-center gap-4"> <Button type="submit" disabled={username && (!formik.isValid || !formik.dirty)} > Submit </Button> </div> </form> ); };
其中方案1最贴合业务逻辑,既保留Formik的验证机制,又能根据场景动态调整规则,确保两种业务场景正常运行。
内容的提问来源于stack exchange,提问作者meguk
相关产品推荐
相关产品推荐

