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

使用Formik开发订餐表单遇双按钮均触发handleSubmit问题求助

问题描述

我用Formik开发订餐项目的表单校验时遇到了问题:表单里设了两个按钮,但不管点哪个都会触发handleSubmit函数。我想让CloseButton关闭表单返回订单列表,可它只会触发Formik的handleSubmit,根本不执行props里的goBack函数(这个函数只是把某个状态设为false)。查了Formik文档也没找到解决办法,相关代码如下:

export default function Checkout(props) {
  function handleSubmit(event) {
    // event.preventDefault();
    console.log("Hello");
  }

  return (
      <Formik
        initialValues={{ userName: "Hi", street: "", postalCode: "", city: "" }}
        onSubmit={handleSubmit}
      >
        {(props) => (
          <Form className={styles["form"]}>
            <div className={styles["form-control"]}>
              <div className={styles["form-control__input"]}>
                <label htmlFor="userName">Your name</label>
                <Field type="text" name="userName" id="userName"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="street">Street</label>
                <Field type="text" name="street" id="street"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="postalCode">Postal code</label>
                <Field type="text" name="postalCode" id="postalCode"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="city">City</label>
                <Field type="text" name="city" id="city"></Field>
              </div>
            </div>
            <div className={styles["form-actions"]}>
              <CloseButton type="button" onClick={props.goBack}>Back</CloseButton>
              <OrderButton type="submit">Confirm</OrderButton>
            </div>
          </Form>
        )}
      </Formik>
  );
}
export default function CloseButton(props) {
  return <button type={props.type} onClick={props.onClick} className={styles["close-button"]}>{props.children}</button>;
}
export default function OrderButton(props) {
  return <button type={props.type} onClick={props.onClick} className={styles['order-button']}>{props.children}</button>
}
解决方案

问题根源是变量名冲突:Formik渲染回调里的props把外部组件的props覆盖了。你在<Formik>{(props) => (...)}</Formik>里用props当参数,这里的props是Formik提供的上下文对象,根本不是父组件传给Checkout的props,所以props.goBack其实是undefined,再加上表单的默认行为,点击按钮就触发了提交。

解决方法很简单:

  1. 把Formik回调里的参数名改成别的,比如formikProps,避免和外部组件的props重名
  2. 确保CloseButton的type="button"正确传递(你的代码已经做到了这一点,默认按钮type是submit,会触发表单提交)

修改后的Checkout组件代码:

export default function Checkout(props) {
  function handleSubmit(event) {
    // event.preventDefault();
    console.log("Hello");
  }

  return (
      <Formik
        initialValues={{ userName: "Hi", street: "", postalCode: "", city: "" }}
        onSubmit={handleSubmit}
      >
        {(formikProps) => ( // 这里修改参数名
          <Form className={styles["form"]}>
            {/* 表单字段部分不变 */}
            <div className={styles["form-control"]}>
              <div className={styles["form-control__input"]}>
                <label htmlFor="userName">Your name</label>
                <Field type="text" name="userName" id="userName"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="street">Street</label>
                <Field type="text" name="street" id="street"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="postalCode">Postal code</label>
                <Field type="text" name="postalCode" id="postalCode"></Field>
              </div>
              <div className={styles["form-control__input"]}>
                <label htmlFor="city">City</label>
                <Field type="text" name="city" id="city"></Field>
              </div>
            </div>
            <div className={styles["form-actions"]}>
              {/* 这里用外部的props.goBack */}
              <CloseButton type="button" onClick={props.goBack}>Back</CloseButton>
              <OrderButton type="submit">Confirm</OrderButton>
            </div>
          </Form>
        )}
      </Formik>
  );
}

这样修改后,点击CloseButton就会执行父组件传入的goBack函数,不会再触发表单提交了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:31:58