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

无输入框时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:02:50